c++ - 基于集合派生对象中存在的类型选择行为的模式

标签 c++ oop inheritance design-patterns virtual-functions

我有一组代表系统模型的对象。这些对象中的每一个都派生自代表抽象“组件”的基类。我希望能够查看系统并根据存在的组件及其顺序选择某些行为。

为了论证,我们将基类称为Component,将实际组件称为InputFilterOutputFilterProcessor。我们可以处理的系统是带有 Processor 和一个或两个过滤器的系统。实际系统的类型更多,它们之间的交互也更复杂,但我认为现在就可以了。

我可以通过 marshalComponentSettings() 函数看到两种“简单”的方法来处理这种情况,该函数采用其中一个集合并计算出如何最有效地设置每个节点。这可能需要以特定方式修改输入或以不同方式拆分它们,因此它并不像为每个组件实现一个虚拟 handleSettings() 函数那么简单。

  • 第一个是使用纯虚函数报告每个类的枚举类型,并使用它们来确定要做什么,dynamic_cast'ing 在需要访问组件特定选项的地方。

    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);
    }
    

似乎第一种是最有效的方法(不需要推测性地测试每个对象以找出它是什么),但即使那样似乎也不太正确(可能是由于那些烦人的细节设备相互影响并泄漏到通用编码代码中)。

有没有比嵌套的条件判断行为更优雅的方式来处理这种情况?甚至是情况或模式的名称?

最佳答案

您的场景似乎是 visitor design pattern 的理想候选者,具有以下角色(请参阅链接中的 UML 模式):

  • objectStructure:您的模型,也就是 Component 的集合
  • 元素:您的组件基类
  • concreteElementX:您的实际组件(InputFilterOutputFilterProcessor、...)
  • 访问者:必须将您的模型作为一组一致的元素来管理的抽象算法系列。
  • concreteVisitorA:你的配置过程。

主要优势:

您的配置/设置符合设计模式的意图:要对对象结构的元素执行的操作。相反,此模式允许您考虑遍历期间遇到的元素的顺序和种类,因为访问者可以有状态

一个积极的副作用是访问者模式将使您的设计具有灵 active ,可以轻松添加具有相似遍历但目的不同的新流程/算法(例如:系统定价、 Material 计划等...)

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; 
    ... 
};

挑战:

访问者面临的主要挑战是设置可以更改配置本身(替换组件?更改顺序),因此您必须注意保持一致容器上的迭代器,同时确保不要多次处理项目。

最佳方法取决于容器的类型,以及您的设置所做的更改类型。但是您肯定需要一些标志来查看哪个元素已被处理,或者一个临时容器(已处理的元素或剩余待处理的元素)。

无论如何,由于访问者是一个类,它还可以将任何此类状态数据封装在私有(private)成员中。

关于c++ - 基于集合派生对象中存在的类型选择行为的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30260441/

相关文章:

c++ - 动态创建继承类,使用 std::map 使用基类指针访问?

来自非成员函数的 C++ 虚拟继承

java - 带有类型列表和继承的方法

c++ - 无法理解 C++ `virtual`

c++ - Boost::spirit 流程规则与分支不正确

c++ - 使用头文件而不是标准命名空间

java - 在Java中_not_调用父类(super class)构造函数的任何方法?

web-services - 是什么让你尝试(或不尝试)一种新的编程语言?

c++ - 图像处理 - 两张图像之间的差异

ios - 如何让两个自定义 UICollectionViewCell 类共享相同的变量名