-
装饰者模式,首先我们要了解,这个设计模式的使用的意图是什么,在设计模式这本书上这样描述的:动态的给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更加灵活。
-
也许我们有的人已经看过了代理模式了,(没看过可以直接略过,我只是简单提一下)那么你是否会感觉到代理模式和装饰者是否相似,确实他们都是在我们方法本来的工作上增加一些操作。在我看来他们之间的区别是装饰者模式需要我们来指定我们需要的添加操作,是一个动态并且主观的操作,而代理模式是在代码中写好了的操作我们在运行的时候无法去修改的,以及代理模式的代理对象客户是并不知道是什么为我们代理的。
-
接着来如果你不太懂他这个描述是什么意思的话我们用设计模式这本书上的一个例子来描述一下
例子写的是在一个wps文档系统上我们需要一个东西来修饰我们的文档内容,比如wps外部的许多滚动条,和边框等来修饰我们的文档对象,设计此对象的时候,我们需要注意,这个边界对于我们的围栏是透明的,即他们应该是松耦合,客户无法察觉出我们是在处理组件还是它的修饰框,形成一个透明围栏。 -
在此之前我们需要提一下,里面的Glyph对象就是我们通过它内部的一种递归的特效通过组合模式设计的对象,Glyph是一个所有类的父类,他的子类是行,列,图片,表格等子对象。接下来我们来看一下书上是如何设计的:
-
我们通过这个图可以了解它用了一个子类来实现Glyph对象的修饰功能上面的图只是简单为我们介绍了一下写好过后在外界看来他们呢的排列,我们实际的类的设计图片:
接下来我们给出一些他们的伪代码:
首先是我们的Glyph图元对象 他是所有图元的父类 draw方法是对我们的组件的绘制工作
//图元对象 所有行列元素的父类
public interface Glyph {
public void draw();
}
修饰者的父类 实现了我们的Glyph对象 目的是基础我们的对象,不是行为。
//我们的Gplyph的实现类 它是一个修饰者,里面可以修饰我们的文档对象
public class MonoGlyph implements Glyph{
protected Glyph glyph;//它所修饰的图元对象
public MonoGlyph(Glyph glyph){
this.glyph=glyph;
}
@Override
public void draw() {
glyph.draw();
}
}
我们的具体的修饰者 继承了上述方法 细化了它的方法
public class Border extends MonoGlyph{//做一个边框的绘制操作
public Border(Glyph glyph) {
super(glyph);
}
@Override
public void draw() {
// TODO Auto-generated method stub
glyph.draw();
System.out.println("执行边框的绘制");
}
}
滚动条的绘制操作
public class Scroller extends MonoGlyph{
public Scroller(Glyph glyph) {
super(glyph);
}
@Override
public void draw() {
// TODO Auto-generated method stub
glyph.draw();
System.out.println("执行滚动条的绘制");
}
}
接下来就是我们的正经的图元对象了
//行 作为图元对象的子类
public class Row implements Glyph{
//一行内可以有多个组件
private List<Glyph> glyphs=new ArrayList<>();
public void addGlyph(Glyph glyph){
this.glyphs.add(glyph);
}
@Override
public void draw() {
//先将自己的子类绘制出来
for(int i=0;i<glyphs.size();i++){
glyphs.get(i).draw();
}
System.out.println("绘制行");
}
}
图片对象 我们假设他是最小的图元 不可以再细分了
public class Image implements Glyph{
//假设图片是最小的组件 它内部不包含任何组件
@Override
public void draw() {
System.out.println("绘制图片对象");
}
}
用我们的main方法作为它的行为驱动:
public class Main {
public static void main(String[] args){
//创建行对象 和图片对象
Row row=new Row();
Image image1=new Image();
Image image2=new Image();
Image image3=new Image();//一行内部包含三张图片
row.addGlyph(image1);
row.addGlyph(image2);
row.addGlyph(image3);
MonoGlyph monoGlyph=new Border(new Scroller(row));//我们在通过滚动条作为图片的透明边界,用border作为滚动条的边界
monoGlyph.draw();
}
}
执行结果:
我认为我们的装饰者不直接继承图元对象,是为了能够和以前的图元对象区分开来,中介隔了一层结构更清晰。还有就是为什么要继承图元对象,可能是一个我们的装饰着本质上就是对我们的图元对象的某些东西进行了填充,所以会实现图元对象表明他们之间的关系。
我们可以主观的创建我们的对象,创建不同种类的修饰框,来修饰我们的文档对象,只需要调用draw方法就可以一直执行下去,我们也可以很简单的新建我们的更多的修饰对象,只需要实现我们的修饰者的父类就可以简单的实现了。