我迷路了,需要一些神圣的指导。对抽象层次的具体实例执行合同
首先第一件事情:假设你有一些很好的,整齐的接口:
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 { ... }
而那些混凝土是reeealy不同的事情。像航天飞机部件(带零件工厂和班车组装线)和蔬菜袋(有农场和.. idk,谁会消费那些蔬菜?)。然而,他们一般都有这样的事情:DoThings()。不管你喜欢什么,假装它就像PackAndSend()或Serialize()或Dispose()一样。没有什么具体的东西,但基于层次结构的合法性。 但这些仍然有更多的差异,比普遍。所以那些具体的消费者倾向于以不同的方式使用它们。换句话说,事实上,他们绝对必须确定它是假定的具体类型。
所以问题在于:我迫使该层次结构的用户在其虚拟覆盖中立即将IPoduct向下压缩为ConcreteProduct。这就让我苦恼。我觉得我错过了一些东西:层次结构存在很大缺陷,缺乏模式知识,有些东西。 我的意思是,我可以确定,ConcreteConsumerB总是收到ConcreteProductB,但它仍然是一个沮丧。你会不会使用一个框架,总是绕过(void *)的,并迫使你把它转换成你认为会来的亚呢?
解决方案我已经考虑:
- 隧道所有conctrete interfeces到IProduct。但是那个产品变成了无法控制的blob,谁可以吃(),BeEaten(),Launch(),Destroy()以及谁知道还有什么。所以这个解决方案似乎没什么比向我下传更好。
- DoThings()可能可以从IProduct解耦成另一个处理程序,它将能够接受所有的混凝土(类似Visitor)。这样IP产品可以被删除,并且会有单独的具体组。但是如果有一个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); } }
这样我就控制了那个低调,但它是stil目前。
不管怎样,这个问题听起来很熟悉吗?有人看到它解决了,或者英雄解决了它自己? C++解决方案会很棒,但我认为任何静态类型的语言就足够了。
如果他们是*“reeealy不同的东西”*是一个继承层次结构和工厂丰盛真的是工作的正确工具? – Flexo
这显然是错误的:'IConcreteConsumer <类型名称_IProduct>' – Nawaz
@awoodland以及它们的区别需要垂头丧气,但有足够的在共同待从一些常见的碱衍生至少为代码复用(除了语义)的缘故。除了派生(还保留了OOP风格)之外,还有另外一种方式来优雅地重用它吗? – Dark