Decorator装饰器模式就是创建一个新类为某一个类动态添加新功能或增强原有的功能.
特点:
装饰器持有一个被装饰的对象;
装饰器和被装饰的对象有相同的接口;
装饰器给被装饰的对象添加额外的功能或增强已有的功能.
即保持接口, 增强功能. 表现形式上最大的特点是装饰器使用并且实现一个父类.
示例代码:
- //装饰器和被装饰的对象共同的接口
- package designpattern.decorator;
- public interface Target {
- public void operation();
- }
- //被装饰的类
- package designpattern.decorator;
- public class ConcreteTarget implements Target{
- public void operation() {
- System.out.println("Original operation.");
- }
- }
- //装饰器1
- package designpattern.decorator;
- public class Decorator1 implements Target{
- private Target target;
- public Decorator1(Target t){
- this.target = t;
- }
- public void operation() {
- System.out.println("Before decorator 1");
- target.operation();
- System.out.println("Atfer decorator 1");
- }
- }
- //装饰器2
- package designpattern.decorator;
- public class Decorator2 implements Target{
- private Target target;
- public Decorator2(Target t){
- this.target = t;
- }
- public void operation() {
- System.out.println("Before decorator 2");
- target.operation();
- System.out.println("Atfer decorator 2");
- }
- }
- //装饰器3
- package designpattern.decorator;
- public class Decorator3 implements Target{
- private Target target;
- public Decorator3(Target t){
- this.target = t;
- }
- public void operation() {
- System.out.println("Before decorator 3");
- target.operation();
- System.out.println("Atfer decorator 3");
- }
- }
- //测试代码
- package designpattern.decorator;
- public class Test {
- public static void main(String[] args){
- Target t = new ConcreteTarget();
- Target obj = new Decorator1(new Decorator2(new Decorator3(t)));
- obj.operation();
- }
- }
这个例子还是显得有些生硬,结合生活中的例子解剖一下装饰器。
一个士兵(Solider)可以行军(march),开火(fire)。 可以用特种装备来装饰这个兵。如:可以用飞行器装配这个兵,使之可飞行, 可以用侦查装备装饰这个兵, 使之可侦查,夜视装备装饰他,使之可夜视。则FlySoldier, ScoutSoldier, NightVisionSoldier是Soldier的装饰器。 而且这些装饰器可以任意组合。
- package designpattern.decorator;
- //兵
- public interface Soldier {
- public String getAbility();
- }
- //中国兵
- package designpattern.decorator;
- public class ChineseSoldier implements Soldier{
- public String getAbility() {
- return "I am a soldier, I can ";
- }
- }
- //会飞的兵
- package designpattern.decorator;
- public class FlySoldier implements Soldier{
- private Soldier soldier;
- public FlySoldier(Soldier s){
- this.soldier = s;
- }
- public String getAbility() {
- return soldier.getAbility() + "fly ";
- }
- }
- //会侦查的兵
- package designpattern.decorator;
- public class ScoutSoldier implements Soldier{
- private Soldier soldier;
- public ScoutSoldier(Soldier s){
- this.soldier = s;
- }
- public String getAbility() {
- return soldier.getAbility() + "scout ";
- }
- }
- //能夜视的兵
- package designpattern.decorator;
- public class NightVisionSoldier implements Soldier{
- private Soldier soldier;
- public NightVisionSoldier(Soldier s){
- this.soldier = s;
- }
- public String getAbility() {
- return soldier.getAbility() + "night vision ";
- }
- }
- //测试用例
- package designpattern.decorator;
- public class Test {
- public static void main(String[] args){
- Soldier s = new ChineseSoldier();
- //通过各种装饰器装备出一个特种兵
- Soldier sprcialSoldier = new NightVisionSoldier(new FlySoldier(new ScoutSoldier(s)));
- System.out.println(sprcialSoldier.getAbility());
- }
- }
通过这个例子进一步分析装饰器的特征:
1 兵不需要知道装备, 而装饰器持有兵,兵是一个简单的兵,而装饰器可以非常复杂, 这是第一个特征;
2 一个兵被装备之后他还是一个兵,即装饰器和被装饰的对象有相同的接口;
3 可以用不同的装备装饰一个兵,这些装备可以随便搭配。
再举一例: 很多老的单元楼的自来水龙头都放在外面, 为了怕别人偷水, 都给自家的龙头加一个盒子锁; 有的人会给龙头加长管子一直牵到自家厨房; 那么加锁, 搭管子就是对龙头进行装饰.并且满足3个特征: 1 装饰器(锁, 管子)都持有原来的水龙头,并增强了原来的水龙头的功能;2 加了锁,套了管子的水龙头还是水龙头; 3 这些装饰器可以方便的拆卸, 组合.
经典案例:
jdk中io使用Decorator对各种流进行封装.
如 BufferedInputStream bi = new BufferedInputStream(new FileInputStream("1.txt"));BufferedInputStream 对FileInputStream进行装饰;InputStream是他们共有的接口.
BufferedReader br = new BufferedReader(new FileReader("1.txt"));
BufferedReader对FileReader进行装饰, Reader是他们共同的接口.
还有更多...
优点:
在拓展类的功能上比继承拥有更大的灵活性
装饰器类可以方便自由的组合
缺点:
使用更少的类,但是构造复杂