转载请注明出处:http://blog.youkuaiyun.com/binbinqq86/article/details/71487272
装饰者模式,提到“装饰”二字,字面意思就是一个事物,可以添加东西去装饰它,比如新买的房子要装修,一个人要买衣服首饰来打扮自己等等。。。老规矩,先通过一个房子装修简单的例子来说明吧:
整体结构图:
图中我们可以看出,首先定义了一个抽象类House,这就是我们从开发商那里拿到的毛坯房,什么都没有,我们在里面定义了一个抽象方法decorator(),子类去继承它来执行具体的装修方案,另外一个就是getDescription(),这个是用来输出当前装修情况和进度的,这个类就是抽象组件类。而MyHouse继承于House,这个就是具体的房子,比如张三的,李四的,等等,属于具体的一个组件。HouseDecorator则是一个抽象装饰者,它抽象了所有装修材料,同样它也是继承House。下面的WindowDecorator,DoorDecorator等等就是具体的装修材料了,你想添加什么东西来装饰你的房子,就可以去继承HouseDecorator这个类,它们都是具体的装饰者类。
下面是伪代码:
package com.example.tb.designpatten.decorator.abstractcomponent;
/**
* Created by tb on 2017/5/10.
* 定义房子抽象基类(抽象组件)
*/
public abstract class House {
/**
* 装修情况说明
*/
protected String description;
public String getDescription(){
return description;
}
/**
* 房子有一个装修的抽象方法
*/
public abstract void decorate();
}
package com.example.tb.designpatten.decorator.abstractdecorator;
import com.example.tb.designpatten.decorator.abstractcomponent.House;
/**
* Created by tb on 2017/5/10.
* 用来装修房子的各种材料的抽象基类(抽象装饰者)
*/
public abstract class HouseDecorator extends House {
/**
* 返回房子装修情况
* @return
*/
public abstract String getDescription();
}
package com.example.tb.designpatten.decorator.concretecomponent;
import com.example.tb.designpatten.decorator.abstractcomponent.House;
/**
* Created by tb on 2017/5/10.
* 具体的需要装修的我的房子(具体组件)
*/
public class MyHouse extends House {
private static final String TAG = "MyHouse";
public MyHouse(){
description=TAG+":还未开始任何装修的毛坯房";
}
@Override
public void decorate() {
//具体装修逻辑,省略。。。
}
}
package com.example.tb.designpatten.decorator.concretedecorator;
import com.example.tb.designpatten.decorator.abstractcomponent.House;
import com.example.tb.designpatten.decorator.abstractdecorator.HouseDecorator;
/**
* Created by tb on 2017/5/10.
* 门(具体装饰者)
*/
public class DoorDecorator extends HouseDecorator {
/**
* 持有一个house类的引用
*/
private House house;
public DoorDecorator(House house){
this.house=house;
}
@Override
public void decorate() {
//执行具体的装修逻辑,代码省略。。。
}
@Override
public String getDescription() {
return house.getDescription()+"——增加了门";
}
}
package com.example.tb.designpatten.decorator.concretedecorator;
import com.example.tb.designpatten.decorator.abstractcomponent.House;
import com.example.tb.designpatten.decorator.abstractdecorator.HouseDecorator;
/**
* Created by tb on 2017/5/10.
* 窗户(具体装饰者)
*/
public class WindowDecorator extends HouseDecorator {
/**
* 持有一个house类的引用
*/
private House house;
public WindowDecorator(House house){
this.house=house;
}
@Override
public void decorate() {
//执行具体的装修逻辑,代码省略。。。
}
@Override
public String getDescription() {
return house.getDescription()+"——增加了窗户";
}
}
整体的五个类的伪代码就全部列出了,很简单。下面我们就写测试代码:
public void test(){
House house=new MyHouse();
house=new WindowDecorator(house);
house=new DoorDecorator(house);
Log.e("Decorator:",house.getDescription());
}
下面看运行结果:
怎么样,跟我们预想的一致,这就是装饰者模式:也成为包装模式,同时它也是继承关系的一种替代方案之一,在现实生活中,你也可以看到很多这样的例子。装饰者模式动态的给一个对象增加一些额外的职责。就增加功能来说,装饰者模式相比生成子类更为灵活。
装饰者模式在Java和Android的源码中都有应用,比如Java中的IO,在java.io包内的类太多了,简直是。。。。。。“排山倒海”。你第一次(还有第二次第三次)看到这些API发出“哇”的惊叹时,放心,你不是唯一受到惊吓的人。InputStream就是这个抽象组件,而FileInputStream,StringBufferInputStream。。。这些就是具体组件,FilterInputStream是一个抽象装饰者,下面的BufferedInputStream,LineNumberInputStream。。。这些就是具体的装饰者了。但是Java I/O也引出装饰者模式的一个“缺点”:利用装饰者模式,常常造成设计中有大量的小类,数量实在太多,可能会造成使用此API程序员的困扰。但是,当你了解了其中的原理之后,就可以很容易地辨别出他们的装饰者类是如何组织的,以方便用包装方式取得想要的行为。
再来看看Android源码中装饰者模式的应用:Context。我们最常接触的一个类,但是可能并不一定有过真正的了解,Context类在Android里是一个抽象类,在我们的装饰者模式里就相当于抽象组件,而ContextImpl就是具体的组件,它继承于Context,并且实现了里面的抽象方法,我们知道Activity继承于ContextThemeWrapper,而ContextThemeWrapper又继承于ContextWrapper,最终的这个ContextWrapper又继承于Context,ContextWrapper就是我们要找的装饰者了,源码中可以看到,ContextWrapper中有个mBase,是一个Context类的引用,这个类里面所有的方法都是调用了ContextImpl中对应的方法,这就是装饰者模式的套路。。。对于具体的方法的包装扩展则有ContextWrapper的具体子类完成,比如我们的Activity、Service、Application。可以看到即便是Android源码中应用,装饰者模式也并不难理解,比较简单。
总结:装饰者模式主要就是抽象组件、具体组件(继承抽象组件并实现里面的方法),抽象装饰者(持有一个抽象组件的引用并且继承抽象组件),数不清的具体装饰者(随意扩展增加功能进行包装)。
好了,今天的讲解到此结束,有不明白的地方可以下面留言,谢谢大家~
365

被折叠的 条评论
为什么被折叠?



