设计模式学习笔记06-Decorator模式

本文主要是看了《设计模式》做的笔记和思考,在此分享仅代表个人观点,如有不对的地方欢迎批评和指正。

基础

当出现需要多个组件组成新的部件,同时不想增加类的数量(即不希望通过继承解决),可以考虑使用Decorator(装饰)模式。该模式下,通过不断地将部件放置到修饰物中,形成新的对象,并且修饰物可以负责将行为(职责)依次向内传递至部件,UML图如下:


Decorator模式-UML.png

使用时是将部件放入到装饰物中。比如Java中BufferedReader与FileReader的关系:

BufferedReader br=new BufferedReader(new FileReader("file.txt"));

代码实现

该模式有几个要点。

1. 需要有一个统一的接口保证一致性。

class Component{
    public void operation();
}

class ConcreteComponent extends Component{
    public void operation(){}
}

class Decorator extends Component{
    private Component component;

    public void operation(){}
    public void setComponent(Component component){
        this.component = component;
        ...
    }    
}

有了统一接口之后,Decorator可以继续放到Decorator中,形成俄罗斯套娃一样的结构,可以方便地得到新的组合对象,同时不增加类的数量。

使用Decorator模式可以很容易地重复添加一个特性,例如在TextView上添加双边框时,仅需将添加两个BorderDecorator即可。而两次继承Border类则极容易出错。

2. 应当保持Component的简单

Component(或者是ConcreteComponent)本身应该很小很简单,且尽量少地存储数据,因为它将多次嵌套在其他对象中。使用过程中的数据可以分散地放在相应修饰物(Decorator)中。

3. Component的接口需要完成最基础的功能

站在Component的角度来说,它是感受不到自己外面到底有多少层壳,而且作出更改的时候,行为是顺着最外层依次向内传递。因此,整个系列的对象都需要做的操作必须要在Component中声明。Decorator中则是顺路加工一下,并不影响到基础功能的执行。

class BorderTextView extends View{
    public void setText(String text){
        ...
        // 设置文字区域的边框宽度
        setTextBorder(1);
        component.setText(text);
    }    
}

class TextView extends View{
    public void setText(String text){
        ...
    }
}

还可以继续嵌套,比如再来个高亮的背景:

class HighlightTextView extends View{
    ...
}

new HighlightTextView(new BorderTextView(new TextView()));

这样就能得到一个即是背景高亮,又有边框的TextView。你可能觉得这跟继承一样,但如果这时候还要一个高亮无边框的TextView呢?继承的话需要多创建一个类,而此处仅需这样就可以得到:

new HighlightTextView(new TextView());

你可能感兴趣的:(设计模式学习笔记06-Decorator模式)