C ++ Decorator模式

时间:2012-01-06 20:44:20

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

我有一个 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: 很抱歉没有那么清楚的解释,因为我不太懂英语

2 个答案:

答案 0 :(得分:4)

根据您的描述,装饰器不是要看的模式。

听起来我只是想设置一个变换器链来操作一个共同的向量 - 即一个简单的功能组合。这与装饰器的区别在于与核心对象的关系 - 你没有为站在中构建一些向量,你正在为构建一些东西在上运作。现在,当您使用多个变换器时,理论上可以将第二个和后来的变换器想象为第一个变换器 decorators ,但考虑到所涉及对象的简单性,尝试将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进一步“简化”此循环(btw)。

变形金刚的动态链与责任链有一些相似之处,除了没有特定对象的概念通过“处理”请求来阻止链,即没有真正的责任与此解决方案相关联 - 每个函数在向量处获得相同的破解。我建议这个模式需要一个更好的名字 - 一个可能已经存在,因为OO编程中的这种功能组合并不罕见,但目前我没有。

答案 1 :(得分:3)

这就是:

#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(而不是引用)上运行。