zoukankan      html  css  js  c++  java
  • 设计模式(6)装饰器(认识程序中的装饰器)

    之前已经看过装饰器模式,但是感觉不是很清晰,但是有一种情况下出的代码,一定是装饰器。

    Widget* aWidget = new BorderDecorator(
    		new BorderDecorator(
    		new ScrollDecorator(
    		new TextField( 80, 24 ))));
    

    可以看到,层层嵌套,每个类都可以按照一定的顺序嵌套多次。

    比如将顺序改为如下:

    Widget* bWidget = new ScrollDecorator(
    		new BorderDecorator(
    		new ScrollDecorator(
    		new TextField( 80, 24 ))));
    

    出现的结果就会不一样,看一下完整的代码。

    #include <iostream>
    
    using namespace std;
    
    /* Component (interface) */
    class Widget {
    	
    public: 
    	virtual void draw() = 0; 
    	virtual ~Widget() {}
    }; 
    
    /* ConcreteComponent */
    class TextField : public Widget {
    	
    private:                  
    	int width, height;
    	
    public:
    	TextField( int w, int h ){ 
    		width  = w;
    		height = h; 
    	}
    	
    	void draw() { 
    		cout << "文本框: " << width << ", " << height << '\n'; 
    	}
    };
    
    /* Decorator (interface) */                                           
    class Decorator : public Widget {
    	
    private:
    	Widget* wid;       // reference to Widget
    	
    public:
    	Decorator( Widget* w )  { 
    		wid = w; 
    	}
    	
    	void draw() { 
    		wid->draw(); 
    	}
    	
    	~Decorator() {
    		delete wid;
    	}
    };
    
    /* ConcreteDecoratorA */
    class BorderDecorator : public Decorator { 
    	
    public:
    	BorderDecorator( Widget* w ) : Decorator( w ) { }
    	void draw() {
    		Decorator::draw();    
    		cout << "   添加边框" << '\n'; 
    	}  
    };
    
    /* ConcreteDecoratorB */
    class ScrollDecorator : public Decorator { 
    public:
    	ScrollDecorator( Widget* w ) : Decorator( w ) { }
    	void draw() {
    		Decorator::draw(); 
    		cout << "   添加滚动" << '\n';
    	}  
    };
    
    int main( void ) {
    	
    	Widget* aWidget = new BorderDecorator(
    		new BorderDecorator(
    		new ScrollDecorator(
    		new TextField( 80, 24 ))));
    	aWidget->draw();
    	delete aWidget;
    	
    	Widget* bWidget = new ScrollDecorator(
    		new BorderDecorator(
    		new ScrollDecorator(
    		new TextField( 80, 24 ))));
    	bWidget->draw();
    	delete bWidget;
    	return 0;
    }
    

    看看运行结果:

    可以给文本框动态的添加形态。

    参考类图如下:

    适用性:

    以下情况使用Decorator模式

    1. 需要扩展一个类的功能,或给一个类添加附加职责。

    2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

    3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

    4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

     

    优点:

    1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。

    2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

    缺点:

    1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。

    2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

    3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

    作者:张锋
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
    更多精彩文章可以观注
    微信公众号 soft张三丰

    微信交流群,添加群主微信,邀请入群
  • 相关阅读:
    centos7修改服务端口(ssh为例)
    VLAN基础知识
    三层交换机与路由器区别
    冲突域和广播域的区分
    LAN口和WAN口的区别是什么?
    内网穿透frp
    linux bash中too many arguments问题的解决方法
    linux日志
    linux服务管理
    OSPF 多区域配置实验
  • 原文地址:https://www.cnblogs.com/skyme/p/2019538.html
Copyright © 2011-2022 走看看