我是从探索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和所有).
所以我想我正在试图找出这种框架要解决的问题.我错过了什么?
在尝试为游戏设计碰撞检测组件时,我提出了以下解决方案.我定义了一个类似于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.但是,我仍然 …