小编idl*_*ire的帖子

为什么要使用服务(IServiceProvider)?

我是从探索XNA框架来探讨这个问题的,但我想了解一般情况.

ISomeService someService = (ISomeService)Game.GetServices(typeof(ISomeService));
Run Code Online (Sandbox Code Playgroud)

然后我们对界面中的任何函数/属性做一些事情:

someService.DoSomething();  // let's say not a static method but doesn't matter
Run Code Online (Sandbox Code Playgroud)

我试图找出为什么这种实现比以下更好:

myObject = InstanceFromComponentThatWouldProvideTheService();

myObject.DoSomething();
Run Code Online (Sandbox Code Playgroud)

当您使用服务方式获取接口时,您实际上只是获取了提供服务的组件实例.对?你不能有一个接口"实例".而且只有一个类可以成为服务的提供者.所以你真正拥有的只是组件类的一个实例,唯一的区别是你只能访问组件对象的子集(界面中的任何子集).

这有什么不同于公共和私人方法和属性?换句话说,组件的公共方法/属性 "接口",我们可以停止所有这些迂回.您仍然可以更改实现"接口"的方式而不会破坏任何内容(直到您更改方法签名,但这也会破坏服务实现).

无论如何,组件和服务之间将存在一对一的关系(多个类不能注册成为服务的提供者),并且我看不到类是提供者的不止一项服务(srp和所有).

所以我想我正在试图找出这种框架要解决的问题.我错过了什么?

c# xna

17
推荐指数
2
解决办法
2万
查看次数

如何避免从接口转换为类

在尝试为游戏设计碰撞检测组件时,我提出了以下解决方案.我定义了一个类似于ICollideable的界面:

interface ICollideable
{
    Sprite Sprite { get; }
    int    Damage { get; }

    void HandleCollision(ICollideable collidedWith);
}
Run Code Online (Sandbox Code Playgroud)

基本上,任何想要参与碰撞检测的游戏对象都必须实现此接口,然后将其自身注册到检测器,该检测器维护一个ICollideable列表.当它检测到碰撞时,它会调用对象上的HandleCollision方法并传入对它碰撞的对象的引用.

我喜欢这个,因为它允许我将所有碰撞算法保存在一个地方,让游戏对象自己决定如何处理碰撞.但由于后者,我发现我必须检查底层对象类型.例如,我不希望玩家互相碰撞,因此在玩家类中可能会有以下内容:

void HandleCollision(ICollideable collidedWith)
{
    if (!(collidedWith is Player)) { // do stuff }
}
Run Code Online (Sandbox Code Playgroud)

等等,我想知道这是否告诉我我的设计不好以及替代品可能是什么.

第二个问题,进一步沿着第一个问题.出于评分的目的,如果一个敌人被一个射弹摧毁,有人需要知道射弹类的"拥有玩家"成员.但是,我的其他碰撞物都没有或者不需要这个属性,所以我发现自己想做(在Enemy HandleCollision中):

void HandleCollision(ICollideable collidedWith)
{
    if (collidedWith is Projectile) {
        Health -= collidedWith.Damage;

        if (Health <= 0) {
            Player whoDestroyedMe = (collidedWith as Projectile).FiredBy
            // ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不清楚如何用更好的设计来处理这个问题.任何见解将不胜感激.

编辑:我想把焦点放在第二个问题上,因为我的直觉告诉我处理这个问题的方法将解决第一个问题.至于第一个问题,我想到了一种抽象这种行为的方法.我可以定义一个枚举:

enum Team
{
    Player,
    Enemy,
    Neither
}
Run Code Online (Sandbox Code Playgroud)

并让ICollideables实现此属性.然后碰撞检测器根本不记录同一"团队"上的可碰撞物之间的碰撞.因此,玩家和玩家弹丸将在一个团队中,敌人和敌人的弹丸将在另一个团队中,并且环境(可能会损坏两者)都不会出现.它不必是枚举,可以是int或字符串或任何东西,并且认为具有相同值的对象不会相互冲突.

我喜欢用简单属性建模行为的想法.例如,如果我想打开"允许友好射击",我所要做的就是创建一个Team值不是玩家团队值的Projectiles.但是,我仍然 …

c# oop interface

9
推荐指数
1
解决办法
1117
查看次数

标签 统计

c# ×2

interface ×1

oop ×1

xna ×1