本文主要是看了《设计模式》做的笔记和思考,在此分享仅代表个人观点,如有不对的地方欢迎批评和指正。
基础
当出现需要多个组件组成新的部件,同时不想增加类的数量(即不希望通过继承解决),可以考虑使用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());
网友评论