Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Language agnostic OOP:何时创建派生类,何时使用条件实现功能?_Language Agnostic_Design Patterns_Oop - Fatal编程技术网

Language agnostic OOP:何时创建派生类,何时使用条件实现功能?

Language agnostic OOP:何时创建派生类,何时使用条件实现功能?,language-agnostic,design-patterns,oop,Language Agnostic,Design Patterns,Oop,什么时候我应该继续生成派生类,什么时候我应该向代码中添加条件? 例如导弹 class Object; class Projectile : public Object; class Missile : public Projectile; class MissileGuided : public Missile; 或者我应该实现导弹代码中的最后一个 void Missile::Update() { if(homing && ObjectExists(Target))

什么时候我应该继续生成派生类,什么时候我应该向代码中添加条件? 例如导弹

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;

在创建派生类和在带有标志或方法的方法中实现特征之间划出一个很好的点?

,您可能需要考虑使用<强>策略模式< /强>,而不是使用这两种方法并封装外部类中的行为。然后可以将这些行为注入到导弹类中,使其成为GuidedMissile或SpaceRocket或任何您需要的东西

通过这种方式,可以避免导弹类中逻辑的过度分支,并且不需要深入研究与深度继承相关的逻辑复杂性

Wikipedia收集了几种语言的模式使用示例:


根据另一个学院的建议,你也可以考虑使用装饰图案。仅强调两个设计问题,如果您选择该路线,这些问题在您的环境中可能很重要:

  • 要仅替换对象行为的某个方面,您需要装饰整个类
  • 如果修饰类(比如导弹)的公共接口需要更改(甚至是一些与其导航方面无关的功能),则必须更改所有修饰类(即GuidedAdminsile、Rocket、FireworkRocket等)以传递该接口
  • 在Decorator中,您希望Decorator添加功能,而不是替换功能。它的工作方式是添加调用其函数,然后调用基类方法。在上面的场景中,这将导致能够有一个装饰地球同步火箭CPU的指南DmissileCPU——显然这不是您想要的。您希望它选择不同的导航策略,而不是将导航策略层层叠加

  • 尽管如此,当提供了导弹装饰的现成不变实现时,可能是“解锁”它并实现战略模式的关键,从而为导弹提供各种必需的行为。

    继承取决于您使用的语言/技术,例如,C++中可以从多个类派生类,但这种结构在爪哇、C、P、PHP等中不可用,而是有抽象类和接口,我想说的是,如果你有一个类,例如,你公司的软件将使用多个数据库管理系统,你可以为这种构造设计一组独立的类,你可以通过使用抽象类来实现,并对你的类集实现多态性,例如:

        public abstract class Database
        {
             public virtual void Connect();
             public virtual int GetNumberOfTables();
    
        }
    
    然后,您可以为特定的SQL Server或Oracle实现派生一个类

        public class SQLServerDatabase : Database
        {
               public override void Connect()
               {
                       // SQL Implementation
               }
    
               public override int GetNumberOfTables()
               {
                     // SQL Implementation
               }  
    
        }
    
    
        public class OracleDatabase : Database
        {
               public override void Connect()
               {
                      // Oracle Implementation
               }
    
               public override int GetNumberOfTables()
               {
                     // Oracle Implementation
               }  
        }
    
    在这样的构造中,您可以使用继承,但避免了我在上面的示例中看到的类逻辑复杂性


    至于可以用来测试是否销毁了对象或垃圾收集器的条件,请将终结队列中的对象设置为不再可用。

    我认为在这种情况下,您应该使用Decorator模式。 您添加的每个新功能都是对原始导弹类的装饰。 例如,您可以创建一个新的装饰性导弹类,该类可以被引导(GuidedMissile),并且可以在水下(UnderwaterMissile),只需装饰该导弹类即可。 好处是Decorator模式在运行时工作,您不需要构建所有具有静态行为的类,但您可以在运行时组合所需的行为。 请看这里:

    问问自己,如何更容易:

  • 阅读并理解代码(小项目部分和整个项目)
  • 在将来更改代码(在预测未来需求时要非常小心,通常最好不要提前调整代码以适应“可能”的更改)
  • 还有一些非常罕见的情况是类层次结构会严重影响性能

    因此,当满足上述条件时,可以创建派生类

        public class SQLServerDatabase : Database
        {
               public override void Connect()
               {
                       // SQL Implementation
               }
    
               public override int GetNumberOfTables()
               {
                     // SQL Implementation
               }  
    
        }
    
    
        public class OracleDatabase : Database
        {
               public override void Connect()
               {
                      // Oracle Implementation
               }
    
               public override int GetNumberOfTables()
               {
                     // Oracle Implementation
               }  
        }