考虑这种专业化的情况,其中较不专业的类需要访问接口类型的对象,但更专业的类需要访问该接口的具体实现:
class IPropulsionMechanism {
public:
virtual void engage() = 0;
virtual void disengage() = 0;
};
class Engine : public IPropulsionMechanism {
};
class Vehicle {
public:
void travelTo(const Destination& dest) {
mPropulsion.engage();
dest.arrival().wait();
mPropulsion.disengage();
}
void SetPropulsion(IPropulsionMechanism& prop) {
mPropulsion = prop;
}
protected:
IPropulsionMechanism& mPropulsion;
};
class Car : public Vehicle {
void adjustTiming() {
// Propulsion Mechanism MUST be Engine
}
问题是Car需要知道它的引擎的细节,没有它就无法运行,但SetPropulsion
方法只接受接口类型。
我之前的一些遗留代码现在通过强制SetPropulsion
强制逆转(通过dynamic_cast
到Engine
)来解决这个问题。显然,这种演员使SetPropulsion
违反了Liskov原则。
我的暂定解决方案是在子类中添加Engine& mEngine
成员,并使用SetEngine
方法:
void SetEngine(Engine& engine) {
mEngine = engine;
Vehicle::SetPropulsion(engine);
}
然而,我唯一的保留是子类可以访问两个基本相同的引用(mPropulsion和mEngine)。
请注意,关系中可能有许多此类成员,汽车需要引擎,CarSeat,AirConVentilation,& c。但车辆必须具有IPropulsionMechanism,ISeat和IVentilation,& c。
我怀疑有一种模式已经涵盖了这种专业化。希望有人可以为我命名。