装饰模式Decorator(结构型)

参考文档:

1.设计模式书籍;

2.http://www.cnblogs.com/bastard/archive/2012/02/02/2336150.html


装饰模式Decorator

一 意图
  动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。——包装器Wrapper。
二 动机
  有时我们希望给某个对象而不是整个类添加一些功能。例如,一个图形用户界面工具箱允许你对任意一个用户界面组件添加一些特性,例如边框,或是一些行为,例如窗口滚动。使用继承机制是添加功能的一种有效途径,从其他类继承过来的边框特性可以被多个子类的实例所使用。但这种方法不够灵活,因为边框的选择是静态的,用户不能控制对组件加边框的方式和时机。
  一种较为灵活的方式是将组件嵌入另一个对象中,由这个对象添加边框。我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。它将客户请求转发给该组件,并且可能在转发前后执行一些额外的动作(例如画一个边框)。透明性使得你可以递归的嵌套多个装饰,从而可以添加任意多的功能,如下图所示。


这样一种结构:


VisualComponent是一个描述可视对象的抽象类,它定义了绘制和事件处理的接口。
注意Decorator类怎样将绘制请求简单地发送给它的组件,以及Decorator的子类如何扩展这个操作。
  Decorator的子类为特定功能可以自由地添加一些操作。
例如,如果其他对象知道界面中恰好有一个ScrollDecorator对象,这些对象就可以用ScrollDecorator对象的ScrollTo操作滚动这个界面。
这个模式中有一点很重要,它使得在VisualComponent可以出现的任何地方都可以有装饰。
因此,客户通常不会感觉到装饰过的组件与未装饰组件之间的差异,也不会与装饰产生任何依赖关系。


三 适用性以及其结构
以下情况使用Decorator模式
1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2 处理那些可以撤消的职责。
3.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
结构:


Component ( VisualComponent )
定义一个对象接口,可以给这些对象动态地添加职责。
• ConcreteComponent ( TextView )
定义一个对象,可以给这个对象添加一些职责。
• Decorator
维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
• ConcreteDecorator(BoaderDecorator,ScrollDecorator)
向组件添加职责。
•Decorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作。

四 效果分析
1 比静态继承更灵活
可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。而继承机制要求为每个添加的职责创建一个新的子类。更灵活的添加装饰:使用Decorator模式可以很容易地重复添加一个特性,例如在TextView上添加双边框时,仅需将添加两个BoarderDecorator即可。而两次继承Boarder类则极容易出错的。
2 避免在层次结构高层的类有太多的特征
Decorator模式提供了一种“即用即付”的方法来添加职责。可以通过定制来逐步的构造复杂的对象。


五 代码实现

Client:

package com.rick.designpattern.decorator;


/**
 * Created by MyPC on 2017/6/1.
 */
public class Client {

    public static void  main(String[] args){
        Windows windows = new Windows();
        windows.setContent(new ScrollDecorator(new BorderDecorator(new TextView("E:\\works\\XinLinDoctor\\demo\\DesignPatternDemo_GitHub>"), 1)));
    }
}

VisualComponent:
package com.rick.designpattern.decorator;

/**
 * Created by MyPC on 2017/6/1.
 */
public class VisualComponent {


    public void draw(){

    }
}
TextView:
package com.rick.designpattern.decorator;

/**
 * Created by MyPC on 2017/6/1.
 */
public class TextView extends VisualComponent {
    private String mText;

    public TextView(String mText) {
        this.mText = mText;
    }

    @Override
    public void draw() {
        System.out.println("TextView is draw in " + mText);
    }
}

Decorator:
package com.rick.designpattern.decorator;

/**
 * Created by MyPC on 2017/6/1.
 */
public class Decorator extends VisualComponent {
    private VisualComponent mVisualComponent;

    public Decorator(VisualComponent mVisualComponent) {
        this.mVisualComponent = mVisualComponent;
    }

    @Override
    public void draw() {
        mVisualComponent.draw();
    }
}
ScrollDecorator:
package com.rick.designpattern.decorator;

/**
 * Created by MyPC on 2017/6/1.
 */
public class ScrollDecorator extends Decorator {
    public ScrollDecorator(VisualComponent mVisualComponent) {
        super(mVisualComponent);
    }

    @Override
    public void draw() {
        super.draw();
        System.out.println("ScrollDecorator is draw");
    }
}
BorderDecorator:
package com.rick.designpattern.decorator;

/**
 * Created by MyPC on 2017/6/1.
 */
public class BorderDecorator extends Decorator {
    private int mWidth;

    public BorderDecorator(VisualComponent mVisualComponent, int width) {
        super(mVisualComponent);
        this.mWidth = width;
    }

    @Override
    public void draw() {
        super.draw();
        System.out.println("BorderDecorator is draw in " + mWidth);
    }
}
Windows:
package com.rick.designpattern.decorator;

/**
 * Created by MyPC on 2017/6/1.
 */
public class Windows {

    public void setContent(VisualComponent visualComponent) {
        System.out.println("window is content");
        visualComponent.draw();
    }
}

六 实例分析
Decorator装饰或者Wrapper包装这个些词太容易让人想到的是图形用户界面,这些控件方面的应用了。但这仅仅只是一种形象的表达而已,不局限于此。
1 For Example:  
Streams是大多数I / O设备的基础抽象结构,它提供了将对象转换成为字节或字符流的操作接口,使我们可以将一个对象转变成一个文件或内存中的字符串,可以在以后恢复使用。一个简单直接的方法是定义一个抽象的Stream类,它有两个子类MemoryStream与FileStream。但假定我们还希望能够做下面一些事情:
• 用不同的压缩算法(行程编码, Lempel-Ziv等)对数据流进行压缩。
• 将流数据简化为7位A S C I I码字符,这样它就可以在A S C I I信道上传输。
Decorator模式提供的将这些功能添加到Stream中方法很巧妙。下面的类图给出了一个解决问题的方法。


       Stream抽象类维持了一个内部缓冲区并提供一些操作( PutInt, PutString)用于将数据存入流中。一旦这个缓冲区满了,Stream就会调用抽象操作HandleBufferFull进行实际数据传输。在FileStream中重定义了这个操作,将缓冲区中的数据传输到文件中去。这里的关键类是StreamDecorator,它维持了一个指向组件流的指针并将请求转发给它,StreamDecorator子类重定义HandleBufferFull 操作并且在调用StreamDecorator的HandleBufferFull操作之前执行一些额外的动作。例如,CompressingStream子类用于压缩数据,而ASCII7Stream将数据转换成7位ASCII码。现在我们创建FileStream类,它首先将数据压缩,然后将压缩了的二进制数据转换成为7位ASCII码,我们用CompressingStream和ASCII7Stream装饰FileStream:

Stream* aStream = new ASCII7Stream (
                     new CompressingStream (
                        new FileStream("aFileStream")
                        )
                        );
aStream->PutInt(12);
aStream->PutString("aString");

七 相关模式:
Adapter模式:Decorator模式不同于Adapter模式,因为装饰仅改变对象的职责而不改变它的接口;而适配器将给对象一个全新的接口。
Composite模式:可以将装饰视为一个退化的、仅有一个组件的组合。然而,装饰仅给对象添加一些额外的职责—它的目的不在于对象聚集。
Strategy模式:用一个装饰你可以改变对象的外表;而Strategy模式使得你可以改变对象的内核。这是改变对象的两种途径。








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中常见的结构型模式包括以下几种: 1. 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另外一个接口。适配器模式可以让原本不兼容的类可以协同工作。 2. 桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。桥接模式可以减少系统中类的数量,并降低它们之间的耦合。 3. 组合模式(Composite Pattern):将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式可以使客户端可以像处理单个对象一样来处理对象的组合。 4. 装饰模式Decorator Pattern):动态地给一个对象添加一些额外的职责,同时又不改变其原有的结构。装饰模式可以在不修改对象的基础上给对象增加新的行为。 5. 外观模式(Facade Pattern):为子系统中的一组接口提供一个统一的接口,以便更方便地访问子系统中的功能。外观模式可以简化客户端与子系统之间的交互。 6. 享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度的对象。享元模式可以提高系统的性能和资源利用率。 7. 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。代理模式可以增加额外的逻辑,比如权限控制、缓存等。 这些模式都有各自的优点和适用场景,在实际开发中可以根据需求选择合适的结构型模式进行设计和实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值