我有一个基类B
和两个派生类D1
,D2
。
class B {
int commonFunc();
virtual int specifyFunc();
}
class D1 : public B {
int specifyFunc();
}
class D2 : public B {
int specifyFunc();
}
现在我满足了我需要扩展基类函数commonFunc()
的要求。由于我不想修改基类中的现有代码,因此我派生了另一个类,如:
class B {
virtual int commonFunc(); // Change to virtual
virtual int specifyFunc();
}
class B2 : public B {
int commonFunc(); // A new commonFunc() to meet new requirement
}
但是,除{I}修改继承层次结构外,D1
和D2
无法使用commonFunc()
中的新B2
。
这是我想出的可能的解决方案
class B {
virtual int commonFunc();
virtual int specifyFunc();
}
class D1 : public B {
int specifyFunc();
}
class D2 : public B {
int specifyFunc();
}
class NewD1 : public D1 {
int commonFunc(); // Overrided commonFunc() in base class
}
class NewD2 : public D2 {
int commonFunc(); // Overrided commonFunc() in base class
}
由于commonFunc()
和NewD1
中的NewD2
完全相同,因此此解决方案涉及较差的代码副本
我正在寻找可以动态扩展基类而不需要对现有类进行太多修改的任何设计模式或解决方案。
答案 0 :(得分:2)
您有多种解决方案。继承只应用于对具有相同责任性的类的代码进行分解。这意味着您的班级Car
不应该从类Logger
继承,因为您需要一些日志记录功能。这将决定选择哪种解决方案。
<强> 1。 D1和D2具有与B
相同的责任性然后,一种更模块化继承的好方法是模式decorator。这样可以让你做你想做的事。只需要一点代码即可获得一个想法:
class B {
virtual int commonFunc();
virtual int specifyFunc();
}
class BDecorator: public B {
B parent;
B(B&);
virtual int commonFunc(); // Implementation forward to parent.
virtual int specifyFunc(); // Implementation forward to parent.
}
class B2: public BDecorator {
int commonFunc();
int specifyFunc();
}
class D1 : public BDecorator {
int specifyFunc();
}
class D2 : public BDecorator {
int specifyFunc();
}
// Use:
B b();
B2 b2(b);
D1 d1(b2);
<强> 2。 D1和D2具有与B
相同的责任性然后你应该使用组合而不是继承。这意味着您应该定义一个纯抽象类D
(一个接口),并使D1
和D2
继承它。然后,在B
的构造函数中,您可以注入D
。 (是的,在这个解决方案中,你必须稍微改变一下B,告诉我这是不是真的有问题。)
class B {
D d;
int commonFunc();
virtual int specifyFunc(); // Do something with d.
B(D);
}
class D {
virtual int func();
}
class D1 : public D {
int func();
}
class D2 : public D {
int func();
}
// Use with B, but you can use B2 (inheriting from B) instead:
D1 d1();
B b1(d1);
D2 d2();
B b2(d2);
我为旧的C ++道歉。
答案 1 :(得分:0)
Interface Design (Program to an interface, not an implementation)
您可以通过使用公共接口(纯抽象类)IB
来避免此类实现依赖性。
你可以改变行为(commonFunc()
)
通过添加新类(NewB
)而不更改现有类
客户端引用公共接口,并且与实现无关。
Decorator Design
如果你不能这样做或者真的想要动态地扩展对象的行为 在运行时,装饰师可能会有所帮助。 但是Decorator只能在执行旧行为之前和/或之后添加行为。
请参阅以下UML图表(如果您不确定如何实施,请告诉我们)。
有关进一步的讨论,请参阅GoF设计模式记忆以进行学习 面向对象的设计&amp;编程/装饰/设计原理(界面设计) 在http://w3sdesign.com。