装饰器模式

什么是装饰器模式

  装饰器模式又称包装(Wrapper)模式,能够实现动态的为对象添加功能。是继承关系的一个替代方案,因为可以在不创造子类的情况下将对象的功能加以扩展。

  通常给对象添加新功能,要么直接修改对象添加,要么派生对应的子类添加或者使用对象组合的方式。在面上对象的设计中,我们应该尽量使用对象组合而不是对象继承来扩展。装饰器模式就是基于对象组合的方式,可以很灵活的给对象添加所需要的功能。

装饰器模式的结构和说明

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

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

  -装饰角色(Decorator):持有一个构件(Component)对象引用,并定义一个与抽象构件接口一致的接口

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

                              

装饰器模式的特点

  -装饰器对象和真是对象有相同的接口。这样客户端对象就可以和真实对象相同的方式和装饰对象交互。

  -装饰对象包含一个真实对象的引用。

  -装饰对象接收所有来自客户端的请求。它把这些请求转发给真实的对象。

  装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不能修改给定对象的构件就可以在外部增加附加功能。在面向对象的设计中,通常是通过集成来实现对给定类的功能扩展

 

示例:

  步骤:

  1. 写一个组件对象接口 Component.java
  2. 写一个类 ConcreteComponent.java 实现 组件对象接口
  3. 写一个装饰器抽象类 Decorator.java 实现组件接口
  4. 写装饰器具体的实现对象 ConcreteDecorator1.java和ConcreteDecorator2.java

步骤一:写一个组件对象接口

package org.burning.sport.design.pattern.decoratorpattern;

/**
 *  @Description: 组件对象接口,可以给这些对象动态的添加职责
 */
public interface Component {
    public void doSomething();
}

步骤二:写一个具体构件角色

package org.burning.sport.design.pattern.decoratorpattern;

/**
 *  @Description: 具体的组件对象,实现了组件接口。该对象通常就是被装饰器装饰的原始对象,可以给这个对象添加职责
 */
public class ConcreteComponent implements Component {
    @Override
    public void doSomething() {
        System.out.println("功能A");
    }
}

 

步骤三:写一个装饰器抽象类

package org.burning.sport.design.pattern.decoratorpattern;

/**
 *  @Description: 所有装饰器的父类,需要定义一个与组件接口一致的接口(主要是为了实现装饰器功能的复用,
 *                 即具体的装饰器A可以装饰另外一个具体的装饰器B,因为装饰器类也是一个Component),并持有一个Component对象,
 *                 该对象其实就是被装饰的对象。如果不实现组件接口类,则只能为某个组件添加单一的功能,
 *                 即装饰器对象不能再装饰其他的装饰器对象
 */
public abstract class Decorator implements Component {
    /**
     * 持有组件对象
     */
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void doSomething() {
        //转发请求给组件对象,可以在转发前后执行一些附加动作
        component.doSomething();
    }
}

 

步骤四:写装饰器具体的实现对象

package org.burning.sport.design.pattern.decoratorpattern;

/**
 *  @Description: 具体的装饰器类,实现具体要向被装饰对象添加的功能。用来装饰具体的组件对象或者另外一个具体的装饰器对象
 */
public class ConcreteDecorator1 extends Decorator {
    public ConcreteDecorator1(Component component) {
        super(component);
    }

    @Override
    public void doSomething() {
        super.doSomething();
        this.doAnotherThing();
    }

    /**
     * 新功能
     */
    private void doAnotherThing() {
        System.out.println("功能B");
    }
}
package org.burning.sport.design.pattern.decoratorpattern;

/**
 *  @Description: 具体的装饰器类,实现具体要向被装饰对象添加的功能。用来装饰具体的组件对象或者另外一个具体的装饰器对象
 */
public class ConcreteDecorator2 extends Decorator{
    public ConcreteDecorator2(Component component) {
        super(component);
    }

    @Override
    public void doSomething() {
        super.doSomething();
        this.doAnotherThing();
    }

    private void doAnotherThing() {
        System.out.println("功能C");
    }
}

 

步骤五:测试

package org.burning.sport.design.pattern.decoratorpattern;

/**
 *  @Description: 装饰器模式(包装模式Wrapper)
 *   装饰模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。
 *   装饰器模式的本质就是动态组合,动态是手段,组合才是目的
 */
public class ClientMain {
    public static void main(String[] args) {
        //节点流
//        Component component = new ConcreteComponent();  //首先创建需要被装饰的原始对象(即要被装饰的对象)
        //过滤流
//        Component component2 = new ConcreteDecorator1(component); //给对象透明的增加功能B并调用
        //过滤流
//        Component component3 = new ConcreteDecorator2(component2);//给对象透明的增加功能C并调用
//        component3.doSomething();

        Component component1 = new ConcreteDecorator1(new ConcreteDecorator2(new ConcreteComponent()));

        component1.doSomething();

    }
}

 

 

https://gitee.com/play-happy/base-project

参考:

[1] 博客, http://blog.csdn.net/hust_is_lcd/article/details/7884320

[2] 博客,http://www.runoob.com/design-pattern/decorator-pattern.html

posted @ 2017-11-02 13:56  寻找风口的猪  阅读(323)  评论(0编辑  收藏  举报