我什么时候应该继续创建派生类,何时应该在我的代码中添加条件?例如导弹
class Object; class Projectile : public Object; class Missile : public Projectile; class MissileGuided : public Missile;
或者我应该在导弹的代码中实现最后一个?
void Missile::Update() { if(homing && ObjectExists(Target)) TurnTowards(Target.Pos) Pos += Motion; }
我认为,对于所有更精细的细节,第二个更好,因为你开始获得事物的组合(例如,一些导弹可能不会在雷达上显示,一些可能是可破坏的,一些可能会获得新目标,如果原件被破坏或超出范围等)
然而,对于在某些情况下共用导弹属性的常规射弹也是如此(例如可能是可破坏的,大型射弹可能在雷达上显示等)
然后我可以说弹丸与船只共享属性(移动,碰撞它们会造成损坏,可能在雷达上显示,可能是可破坏的......)
然后一切都像3个类一样回归:
class Entity; class Object : public Entity; class Effect : public Entity;
在创建派生类和使用标志或其他东西实现方法中的功能之间划清界线的好处在哪里?
您可能需要考虑使用策略模式而不是两种方法,并将行为封装在外部类中.然后可以将行为注入到Missile类中,使其成为GuidedMissile或SpaceRocket或您需要的任何其他内容.
这样可以避免Missile类中逻辑的过度分支,并且您不需要进入与深度继承相关的逻辑复杂性.
维基百科有几种语言的模式使用样本集合:http: //en.wikipedia.org/wiki/Strategy_pattern
interface INavigable { Course calcCourse (Position current, Destination dest); } Class GeoStationaryRocketCPU implements INavigable { Course calcCourse (Position current, Destination dest) { return dest.getShortestRouteTo (current).getCourse(); }; } Class GuidedMissileCPU implements INavigable { Course calcCourse (Position current, Destination dest) { return dest.getLowestAltRouteTo (current).getCourse(); }; } class Missile { INavigable CPU; void setCPU (INavigable CPU) { this.CPU = CPU; } void fly () { ... course = this.CPU.calcCourse (pos, dest); ... } }
正如另一位同事所建议的那样,您也可以考虑使用Decorator模式.只是为了突出显示在您的上下文中可能很重要的几个设计问题,如果您采取这种方式:
要仅替换对象行为的某个方面,您需要装饰整个类.
如果装饰类的公共接口(比如导弹)要改变(甚至一些与导航方面无关的功能),你将不得不改变所有的装饰类(即GuidedMissile,Rocket,FireworkRocket等)来传递接口.
在Decorator中,你会期望装饰器会添加功能,而不是替换它.它通过添加调用其函数然后调用基类方法来工作.在上面的场景中,这将导致能够有一个装饰GeoStationaryRocketCPU的GuidedMissileCPU - 显然这不是你想要的.您希望它选择不同的导航策略,而不是将导航策略叠加在一起.
尽管如此,当提供现成的导弹装饰的不可变实施时,可能是"解锁"它并实施战略模式的关键,为导弹提供各种所需的行为.