我迷路了,需要一些神圣的指导。
首先要做的事情:假设您有一些非常整洁的界面:
class IProduct
{
public:
virtual void DoThings();
}
enum ProductType
{
...
}
class IProducer
{
public:
virtual IProduct* Produce( ProductType type );
}
class IConsumer
{
public:
virtual void Consume( IProduct* product );
}
它很简单:抽象工厂,将调用接口的抽象消费者,这些新生成的 IProducts 很乐意提供。但棘手的部分来了。假设有两个(或更多)平行的具体组:
class ConcreteProducerA : public IProducer { ... }
class ConcreteConsumerA : public IConsumer { ... }
class ConcreteProductA : public IProduct { ... }
class ConcreteProducerB : public IProducer { ... }
class ConcreteConsumerB : public IConsumer { ... }
class ConcreteProductB : public IProduct { ... }
这些混凝土是完全不同的东西。就像航天飞机零件(带有零件工厂和穿梭装配线)和蔬菜袋(带有农场和.. idk,谁会食用这些蔬菜?)。然而他们一般都有那个东西:DoThings()。假设它是 PackAndSend()、Serialize() 或 Dispose(),无论你喜欢什么。没有什么具体的,但作为层次结构的基础是合法的。但这些仍然有更多的差异,而不是一般性。所以那些 ConcreteConsumers 倾向于以不同的方式使用它们。如此不同,事实上,他们绝对必须确定它应该是具体类型。
所以这就是问题所在:我现在正在强迫该层次结构的用户在他们的虚拟覆盖中将 IPoduct 向下转换为 ConcreteProduct。这让我很难受。我觉得我错过了一些东西:层次结构中的一个大缺陷,缺乏模式知识,一些东西。我的意思是,我可以确定,ConcreteConsumerB 总是收到 ConcreteProductB,但它仍然很沮丧。你会使用一个框架,它总是绕过 (void*)'s 并迫使你将它投射到你认为会来的时候吗?
我已经考虑过的解决方案:
- 将所有具体的接口都隧道化到 IProduct 中。但是那个产品会变成无法控制的 blob,谁可以吃()、吃()、启动()、销毁(),谁知道还有什么。所以这个解决方案对我来说似乎没有什么比沮丧更好的了。
- DoThings() 可能会从 IProduct 分离到另一个处理程序中,该处理程序将能够接受所有具体的(类似访问者)。这样可以删除 IProduct 并且会有单独的具体组。但是,如果有一个 SemiConcrete 层,它为这些具体组实现了一些通用功能呢?比如贴标签、变形、按摩等等。另外,当需要添加另一个具体组时,我将被迫更改该访问者,这会增加耦合。
(ab) 使用模板。这在目前看来是明智的。类似的东西
template < typename _IProduct > class IConcreteProducer : public IProducer { public: virtual _IProduct* Produce( _IProduct::Type type ) = 0; virtual _IProduct::Type DeduceType( ProductType type ) = 0; virtual IProduct* Produce( ProductType type ) { return IConcreteProducer<typename _IProduct>::Produce( DeduceType( type ) ); } } template < typename _IProduct > class IConcreteConsumer : public IConsumer { public: virtual void Consume( _IProduct* product ) = 0; virtual void Consume( IProduct* product ) { IConcreteConsumer<typename _IProduct>::Consume( (_IProduct*)product ); } }
这样我就可以控制那种沮丧,但它仍然存在。
无论如何,这个问题对某人来说听起来很熟悉吗?有人看到它解决了,还是自己英勇地解决了它?C++ 解决方案会很棒,但我认为任何静态类型的语言都足够了。