装饰器模式

参考文章:

http://blog.csdn.net/hust_is_lcd/article/details/7884320

http://blog.csdn.net/hguisu/article/details/7531960


定义:

    是指对一个类的功能进行扩展,同时保证不修改原类的代码。(遵循开闭原则)

解决的问题:

  • 需要动态地扩展一个类的功能时,非常灵活,可增可消。(注意,继承只能静态地扩展,无法消去)。
  • 装饰模式用于弥补类继承模式无法遵循里氏代换原则的不足。

模式组成:

抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,

即可以给这些对象动态地添加职责。

具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。

可以给这个类的对象添加一些职责

抽象装饰器(Decorator):维持一个指向构件Component对象的实例,

并定义一个与抽象组件角色Component接口一致的接口

具体装饰器角色(ConcreteDecorator):向组件添加职责。

uml类图:


装饰器模式

优点:

  • 动态的扩展一个类的功能,可增加可删除。(继承只能增加功能,无法删除)
  • 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
  • 弥补类继承模式无法遵循里氏代换原则的不足。
  • 避免在层次结构高层的类有太多的特征 。Decorator模式提供了一种“即用即付”的方法来添加职责

应用场景:

  • 需要在不影响其他对象的情况下,以动态、透明的方式给对象添加职责
  • 如果不适合使用子类来进行扩展的时候,可以考虑使用装饰器模式


Java中的IO是明显的装饰器模式的运用。FilterInputStream,FilterOutputStream,FilterRead,FilterWriter分别为具体装饰器的父类,相当于Decorator类,它们分别实现了InputStream,OutputStream,Reader,Writer类(这些类相当于Component,是其他组件类的父类,也是Decorator类的父类)。继承自InputStream,OutputStream,Reader,Writer这四个类的其他类是具体的组件类,每个都有相应的功能,相当于ConcreteComponent类。而继承自FilterInputStream,FilterOutputStream,FilterRead,FilterWriter这四个类的其他类就是具体的装饰器对象类,即ConcreteDecorator类。通过这些装饰器类,可以给我们提供更加具体的有用的功能。如FileInputStream是InputStream的一个子类,从文件中读取数据流,BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区类保存输入流中的数据。我们使用如下的代码来使用BufferedInputStream装饰FileInputStream,就可以提供一个内存缓冲区来保存从文件中读取的输入

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); //其中file为某个具体文件的File或者FileDescription对象   

装饰器模式vs代理模式


相同点:实现基本相同

区别:

  • 代理模式中,代理类对被代理的对象有控制权,决定其执行或者不执行。
  • 装饰模式中,装饰类对代理对象没有控制权,只能为其增加一层装饰,以加强被装饰对象的功能,仅此而已。

举个栗子:

定义抽象角色

abstract class Food {
    public abstract String getDesc();
}

定义抽象装饰器

abstract class FoodDecoration extends Food {
    @Override
    public abstract String getDesc();
}

定义具体的角色

class Duck extends Food {
    @Override
    public String getDesc() {
        return "鸭肉";
    }
}

定义具体装饰器

class RoastFood extends FoodDecoration {
    private Food food;

    public RoastFood(Food f) {
        this.food = f;
    }
    @Override
    public String getDesc() {
        return getDecoration() + food.getDesc();
    }
    private String getDecoration() {
        return "烤";
    }
}

定义具体装饰器

class SteamedFood extends FoodDecoration {

    private Food food;

    public SteamedFood(Food f) {
        this.food = f;
    }

    @Override
    public String getDesc() {
        return getDecoration() + food.getDesc();
    }

    private String getDecoration() {
        return "蒸";
    }
}

客户端调用

public static void main(String[] args) {
        // 创建食物
        Food food = new Duck();
        // 加入修饰者
        RoastFood rf = new RoastFood(food);
        System.out.println(rf.getDesc());
        // 加入又一个修饰者
        SteamedFood sf = new SteamedFood(rf);
        System.out.println(sf.getDesc());
    }

输出

装饰器模式