我有一组对象,代表系统的模型。这些对象中的每一个都派生自一个表示抽象"组件"的基类。我希望能够查看系统,并根据存在的组件和顺序选择某些行为。
为了论证,我们调用基类Component
和实际组件InputFilter
,OutputFilter
和Processor
。我们可以处理的系统是具有Processor
和一个或两个过滤器的系统。实际的系统有更多类型和更复杂的交互,但我认为现在这样做。
我可以看到两个"简单"使用marshalComponentSettings()
函数处理这种情况的方法,该函数采用其中一个集合并找出如何最有效地设置每个节点。这可能需要以某种方式修改输入或以不同的方式将它们拆分,因此它不像每个组件实现虚拟handleSettings()
函数那么简单。
第一种是使用纯虚函数从每个类报告枚举类型,并使用这些来计算要执行的操作,dynamic_cast
以及访问组件特定选项所需的位置。
enum CompType {
INPUT_FILTER,
OUTPUT_FILTER,
PROCESSOR
}
void marshal(Settings& stg)
{
if (comps[0].type() == INPUT_FILTER)
setUpInputFilter(stg); //maybe modified the stg, or provides other feedback of what was done
// something similar for outputs
setUpProcessor(stg);
}
第二个是dynamic_cast
到任何可能是此函数中的选项并使用该成功与否的成功(以及可能需要的演员对象)来确定要执行的操作。
void marshal(Settings& stg)
{
if (InputFilter* filter = dynamic_cast<InputFilter*>(comp[0]))
setUpInputFilter(stg); //maybe modified the stg, or provides other feedback of what was done
// something similar for outputs
setUpProcessor(stg);
}
似乎第一种是最有效的方法(不需要推测性地测试每个物体以找出它是什么),但即使这样看起来也不对(可能是因为这很烦人)这些设备如何相互影响泄漏到一般封送代码中的细节。)
有没有一种更优雅的方法来处理这种情况,而不是一组条件确定行为?甚至是情况或模式的名称?
答案 0 :(得分:1)
您的方案似乎是 visitor design pattern 的理想候选者,具有以下角色(请参阅链接中的UML架构):
Component
Component
基类InputFilter
,OutputFilter
,Processor
,...)主要优势:
您的配置/设置对应于设计模式的意图:要对对象结构的元素执行的操作。相反,此模式允许您考虑遍历期间遇到的元素的顺序和类型,因为访问者可以 有状态 。
一个积极的副作用是,访问者模式将为您的设计提供灵活性,可以轻松添加具有类似遍历但目的不同的新流程/算法(例如:系统定价,物料计划等等)
class Visitor;
class Component {
public:
virtual void accept(class Visitor &v) = 0;
};
class InputFilter: public Component {
public:
void accept(Visitor &v) override; // calls the right visitor function
};
...
class Visitor
{
public:
virtual void visit(InputFilters *c) = 0; // one virtual funct for each derived component.
virtual void visit(Processor *c) = 0;
...
};
void InputFilter::accept(Visitor &v)
{ v.visit(this); }
...
class SetUp : public Visitor {
private:
bool hasProcessor;
int impedenceFilter;
int circuitResistance;
public:
void visit(InputFilters *c) override;
void visit(Processor *c) override;
...
};
<强>挑战:强>
您对访问者的主要挑战,但也有其他选择,是设置可以更改配置本身(替换组件?更改顺序),因此您必须照顾保持一个合作伙伴容器上的迭代器,同时确保不要多次处理项目。
最佳方法取决于容器的类型以及设置正在执行的更改类型。但是你肯定需要一些标志来查看哪个元素已被处理,或者是一个临时容器(处理的元素或剩余要处理的元素)。
在任何情况下,由于访问者是一个类,它还可以将任何此类状态数据封装在私有成员中。