设计模式——(五)装饰模式

装饰模式(Decorator)

动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。(将所需功能安照正确的顺序串联起来进行控制。衣服在内部穿好在show)

经典的错误代码:Person类 里面不同的方法,穿不同的衣服。新增种类,则新增函数,客户端代码都需要重新改,违背了开放封闭原则。

UML类图

在这里插入图片描述
Component(组件)是定义一个对象接口,可以给这些对象动态的添加职责。ConcreteComponent(具体组件)是定义一个具体的对象,也可以给这个对象添加一些职责。
Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,无需知道Decorator的存在的。至于ConcreteComponent就是具体的装饰对象,起到给Component添加职责的功能。实际中可将ConcreteComponent 和Component合并为一个类

C++代码实现

//组件类
class Component {
public:
    virtual void Operator() { cout << "Component::Operator():组件类的操作 " << endl; }
};
//具体组件类
//具体的装饰对象,起到给Component添加职责的功能
class ConcreteComponent: public Component {
public:
    void Operator() 
    {
        cout << "ConcreteComponent::Operator():具体对象的操作 " << endl;
    }
};
// 装饰抽象类,继承了Component,从外类来扩展Component类的功能,
//但对于Component来说,无需知道Decorator的存在的。
class Decorator :public Component {
private:
    Component *_component;
public:
    //设置Component
    void setComponent(Component *component) 
    {
        this->_component = component;
    }
    //重写 Operator() 实际执行的是ComponentOperator()
    void Operator()
    {
        //if (_component!=NULL) 
        {
           // cout << "Decorator::Operator():装饰抽象类的操作 " << endl;
            _component->Operator();
        }
    }
};
class ConcreteDecoratorA :public Decorator {
private:
    int _a;  //本类独有功能,以区别ConcreteDecoratorB
public:
    void Operator()
    {
        Decorator::Operator();//先运行Component::Operator(),在执行本类的功能,相当于对Component进行装饰
        _a = 10;
        cout << "ConcreteDecoratorA::Operator():ConcreteDecoratorA的操作 :"<<_a << endl;    
    }
};
class ConcreteDecoratorB :public Decorator {

public:
    //本类独有功能,以区别ConcreteDecoratorA
    void funB() 
    { cout << "ConcreteDecoratorB::funB();"<< endl; }  
    void Operator()
    {
        Decorator::Operator();//先运行Component::Operator(),在执行本类的功能,相当于对Component进行装饰
        funB();
        cout << "ConcreteDecoratorB::Operator():ConcreteDecoratorB的操作 :"<< endl;
       
    }
};

int main()
{
    std::cout << "Hello World!\n";
    Component *cc= new Component;
    ConcreteDecoratorA *a1 = new ConcreteDecoratorA;
    ConcreteDecoratorB *b1 = new ConcreteDecoratorB;
    a1->setComponent(cc);     //装饰的方法首先ConcreteComponent实例化对象cc,然后用ConcreteDecoratorA实例化的对象a1包装cc
    b1->setComponent(a1);      //用ConcreteDecoratorB实例化的对象b1包装a1,调用b1的Operator();
    b1->Operator();
}
输出:
Component::Operator():组件类的操作
ConcreteDecoratorA::Operator():ConcreteDecoratorA的操作 :10
ConcreteDecoratorB::funB();
ConcreteDecoratorB::Operator():ConcreteDecoratorB的操作 :
//    //首先ConcreteDecoratorB 的Operator(),先执行基类Decorator::Operator() ,在基类Decorator::Operator()中
    //会根据设置的Component对象是谁,决定调用谁的Operator(),由于b1->setComponent(a1);设置Component对象为ConcreteDecoratorA
//故到ConcreteDecoratorA 的Operator(),由于A设置的Component对象是Component,故先Component::Operator(),然后A的。然后B的。
//栈中 ConcreteDecoratorB::Operator()-》ConcreteDecoratorA::Operator()->Component::Operator()。 故打印顺序如上。

3.何时用。装饰模式是对已有功能动态的添加更多功能的一种方式。经典的错误做法,向旧类中添加新代码,新加的代码装饰了原有类的核心职责或是主要行为,增加了主类的复杂程序。
而装饰模式提供了一个非常好的解决方案,把每个要装饰的功能单独放在一个类中,并让这个类包装它所要修饰的对象,因此当需要执行特殊行为时,客户端代码就可以在运行时根据需要有选择地,按顺序地使用装饰功能包装对象了。
4.优点:把类中装饰功能从类中搬移去除,这样可以简化原有的类。有效地把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑。
注意:装饰模式的装饰顺序很重要。比如加密数据和过滤词汇都可以是数据持久化前的装饰功能,但若先加密了数据再用过滤功能就会出问题。最理想的情况保证装饰类之间彼此独立,这样他们就饿可以以任意的顺序进行组合。(先穿西装,在套T恤不是个好的方法)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值