装饰模式(Decorator Pattern)

来源:互联网 发布:微信推广淘宝商品 编辑:程序博客网 时间:2024/05/16 07:25

装饰模式:

以对客户透明的方式动态地给一个对象附加上更多的责任。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。若要扩展功能,装饰者比继承提供了更有弹性的替代方案。

装饰模式的类图如下:


在装饰模式中的角色有:

  ●  抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。

  ●  具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。

  ●  装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。

  ●  具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。

源代码:

抽象构建component:

public interface Animal {    void behavior();}
具体构建concreteComponent:

public class Dog implements Animal {    public void behavior() {        System.out.println("小狗会跑");    }}
装饰者decorator:

public class Sports implements Animal {    private Animal animal;    public Sports(Animal animal){        this.animal = animal;    }    public void behavior(){        this.animal.behavior();    }}
具体状态concreteDecorator:

public class Jump extends Sports {    public Jump(Animal animal) {        super(animal);    }    @Override    public void behavior() {        super.behavior();        System.out.println("会跳");    }}
public class Sleep extends Sports{    public Sleep(Animal animal) {        super(animal);    }    public void behavior(){        super.behavior();        System.out.println("累了会睡觉");    }}
public class Thought extends Sports{    public Thought(Animal animal) {        super(animal);    }    public void think(){        System.out.println("这是一只会思考的动物");    }}
测试代码:

public class Test {    public static void main(String[] args) {        //透明的装饰模式        Animal animal = new Dog();        animal.behavior();        System.out.println();        animal = new Jump(animal);        animal.behavior();        System.out.println();        animal = new Sleep(animal);        animal.behavior();        System.out.println();        //半透明的装饰模式        Thought thought = new Thought(new Dog());        thought.think();        thought.behavior();    }}
输出结果:

小狗会跑

小狗会跑
会跳

小狗会跑
会跳
累了会睡觉

小狗会跑
这是一只会思考的动物


可以看到我在测试代码里面分为了2个部分:透明的状态模式,半透明的装饰模式。下面就以这2个部分来介绍一下装饰模式的使用。


我们定义了Dog类,定义了他的行为是“小狗会跑”。同时,我们又定义了一下装饰者Jump,Sleep,通过下面这个代码活动一个动物

Animal sleep = new Sleep(new Jump(new Dog()));
这只动物的行为其实就是测试方法中输出的:

小狗会跑
会跳
累了会睡觉

这就是文字开头说的通过创建一个包装对象,也就是装饰来包裹真实的对象,动态地给一个对象附加上更多的责任。

这里动态的增加的责任就是跳和睡觉。


那么什么是透明和半透明呢?

透明的装饰模式:

理想的装饰模式开头也提到了:以对客户透明的方式动态地给一个对象附加上更多的责任。

这里的对客户透明实际上就是面向接口编程

Animal sleep= new Sleep(new Jump(new Dog()));
还是用这个例子来说明,我们定义的是Animal,是一个接口,而不是他正在的实现Sleep类。也就是说装饰模式对客户端的透明性要求程序不要声明一个ConcreteComponent类型的变量,而应当声明一个Component类型的变量。因此我们应该这样写

Animal dog = new Dog();Animal jump = new Jump(new Dog());
而不应该这样写

Dog dog = new Dog();Jump jump = new Jump(new Dog());
半透明的装饰模式:

然而,纯粹的装饰模式很难找到。装饰模式的用意是在不改变接口的前提下,增强所考虑的类的性能。在增强性能的时候,往往需要建立新的公开的方法。就好比我们需要的不仅仅是有行为能力的动物,还需要能思考的动物时,我们定义了一个Thought类,提供了思考的功能。那么需要使用这个think()方法的时候,就不能通过声明Animal接口来获得这个功能,而是声明Thought的引用。

//半透明的装饰模式        Thought thought = new Thought(new Dog());        thought.think();        thought.behavior();

装饰模式的优点

  (1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。

  (2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

装饰模式的缺点

  由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。



1 0
原创粉丝点击