【问题标题】:C++ Decorator patternC++ 装饰器模式
【发布时间】:2012-02-04 13:27:48
【问题描述】:

我有一个 vector 和几个类(位于单独的文件中)来修改一个。
我想全局访问std::vector,但只能在派生类中 当每个调用存储上一个结果时,最后一个对象应该返回总结果

您能解释一下如何使用带有std::vector 的装饰器模式构建高性能接口吗?
我可能错了,可能需要其他模式。

// A.h
class A () {
      public : 
           vector<int> set(vector<int> &vec);

            //return total result
           vector<int> get() {
               return vector;
           }
};

// B.h
class B () {
    //add new elements into vector
    //for example, add 2,3,4
};

// C.h
class C () {
    //remove some elements from vector
    //for example, remove last element
};

//...

// main.cpp
#include "A.h"
#include "B.h"
#include "C.h"

int main () {

    vector<int> set;
    set.push_back(1); //1

    C obj(new B(new A()));
    obj.set(set);
    obj.get(); // stores 1,2,3 (added by classes A, B, C)
}

所以,我不想这样做:

vector<int> set1;
set1.push_back(1);

A *A_init;
A_init->set(set1); //add 1

vector<int> set2 = A_init->get();

B *B_init;
B_init->set(set2); //add 2, stores 1,2

vector<int> set3 = B_init->get();

C *C_init;
C_init->set(set3); //add 3, stores 1,2,3

vector<int> set4 = C_init->get();

/..

我想这样做:

vector<int> set;
set.push_back(1);

C obj(new B(new A()));
obj.set(set);
obj.get(); // stores 1,2,3

我有一个模式装饰器的简单实现。
但这不是我所需要的((

#include <iostream>
#include <memory>

class A {
    public:
        virtual void operation() = 0;
    };

class Component : public A {
    public:
        virtual void operation() {
            std::cout<<"World!"<<std::endl;
        }
};

class B : public A {
    std::unique_ptr<A> add;

public:
    B(A *component): add(component) {}

    virtual void operation() {
        std::cout << ", ";
        add->operation();
    }
};

class C : public A {
    std::unique_ptr<A> add;

public:
    C(A *component): add(component) {}

    virtual void operation() {
            std::cout << "Hello";
            add->operation();
    }
};

int main() {
    C obj(new B(new Component()));
    obj.operation(); // prints "Hello, World!\n"

    return 0;
}

PS: 抱歉解释的不是很清楚,因为我不太懂英文

【问题讨论】:

  • 你能试着改写问题吗?我不清楚在问什么。最简单的情况是,您是想将vector&lt;int&gt; 的元素相加还是完全相加?
  • 您的第一个代码块有一些严重的问题,例如未初始化的init 变量。
  • @hmjd,我想在全局范围内(或类似的)修改vector&lt;int&gt;(添加或删除元素),但使用多个类并返回总结果(修改后的向量)。
  • 使用本地 vector&lt;int&gt; 并通过引用将其传递给多个类/方法进行修改比在全局范围内拥有一个对象更可取。
  • 我有一个类层次结构,其中每个类都返回公共向量的修改版本。而且我不想为每个类做单独的初始化。这是选择Decorator pattern的主要原因

标签: c++ design-patterns inheritance stl decorator


【解决方案1】:

根据您的描述,Decorator 不是要查看的模式。

在我看来,你只是想建立一个转换器链来操作一个公共向量——即一个简单的函数组合。这与 Decorator 的不同之处在于与核心对象的关系 - 您不是在构建一些东西来代替向量,而是在构建一些东西来对其进行操作。现在,当您使用多个转换器时,理论上您可以将第二个和以后的转换器想象为第一个的 装饰器,但考虑到所涉及对象的简单性,尝试将 GoF 装饰器实现应用于您的情况可能是会矫枉过正。

您可以通过执行以下操作来接吻:

#include <vector>

using namespace std;
typedef vector<int> ivec;

ivec& a(ivec& v) {
    v.push_back(1);
    return v;
}

ivec& b(ivec& v) {
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    return v;
}

ivec& c(ivec& v) {
     v.pop_back();
     return v;
}

共有三个简单的转换函数,每个函数都这样编写,以便将一个的输出直接馈送到下一个的输入。然后您可以执行以下操作:

ivec& xform(ivec& v) {
    return c(b(a(v)));
}

ivec v;
xform(v);

如果您只想静态构建最终转换并应用它。

作为替代实现,假设您想动态地构建一组转换器。在这种情况下,您可以将函数推送到转换器向量中并逐个应用它们:

#include <vector>
using namespace std;

typedef ivec& (*ivec_xformer)(ivec&);
typedef vector<ivec_xformer> xform_vec;
xform_vec xforms;
xforms.add(&a);
xforms.add(&b);
xforms.add(&c);

ivec v;
for (xform_vec::iterator i = xforms.begin(); i != xforms.end(); ++i) {
   (*i)(v);
}

最后这个循环,顺便说一句,如果你愿意的话,可以用boost::bindstd::for_each 进一步“简化”。

转换器的动态链与责任链有一些相似之处,除了没有让特定对象通过“处理”请求来停止链的概念,即没有真正的responsibility 与此解决方案相关联——每个函数在向量处获得相同的裂缝。我建议这种模式需要一个更好的名称——可能已经存在一个,因为这种面向对象编程中的函数组合并不少见,但目前我不知道。

【讨论】:

    【解决方案2】:

    这里是:

    #include <vector>
    #include <cstdio>
    
    /* A class that operates on an std::vector. */
    class Vector
    {
    public:
        virtual std::vector<int> & getVector() = 0;
        virtual void operation() = 0;
        virtual ~Vector() {}
    };
    
    /* Basic implementation of Vector. */
    class BasicVector : public Vector {
    public:
        BasicVector(std::vector<int> & refVector) : intVector(refVector) {}
        void operation() {
            intVector.push_back(2);
        }
        std::vector<int> & getVector() {
            return intVector;
        }
    private:
        std::vector<int> & intVector;
    };
    
    /* First decorator. */
    class VectorDecorator1 : public Vector
    {
    public:
        VectorDecorator1(Vector & refVec) : intVec(refVec) {}
        std::vector<int> & getVector() {
            return intVec.getVector();
        }
        void operation() {
            intVec.operation();
            intVec.getVector().push_back(3);
        }
    private:
        Vector & intVec;
    };
    
    /* Second decorator. Others can be easily added in the future. */
    class VectorDecorator2 : public Vector
    {
    public:
        VectorDecorator2(Vector & refVec) : intVec(refVec) {}
        std::vector<int> & getVector() {
            return intVec.getVector();
        }
        void operation() {
            intVec.operation();
            intVec.getVector().push_back(4);
        }
    private:
        Vector & intVec;
    };
    
    int main(int argc, char *argv[])
    {
        std::vector<int> my_vector;
        my_vector.push_back(1);
        BasicVector basic_vector(my_vector);
        VectorDecorator1 vd1(basic_vector);
        VectorDecorator2 vd2(vd1);
        vd2.operation();
        for(unsigned i = 0; i < my_vector.size(); i++) {
            printf("%d\n", my_vector[i]);
        }
        return 0;
    }
    

    注意:如果您愿意,可以轻松更改 BasicVector 以使其在自己的 std::vector(而不是引用)上运行。

    【讨论】:

      猜你喜欢
      • 2014-10-29
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      • 2018-04-10
      相关资源
      最近更新 更多