装饰模式(Decorator)

装饰模式(Decorator或 Wrapper)(Java IO过滤流用到的正是这个模式):

    之前总是先罗列基本概念再介绍代码,这次先把代码罗列出来再写基本的概念clip_image002

    以上是UML类图,先把基本的代码罗列出来:

package com.designpatten.decorator;
interface  Component {
    public void doSomething();
}
package com.designpatten.decorator;

public class concreteComponent implements Component{

    public void doSomething() {
        System.out.println("功能A");
        
    }

}
package com.designpatten.decorator;

abstract class Decorator implements Component {

    private Component component;
    
    public Decorator (Component component){
        this.component=component;
    }
    public void doSomething() {
        //调用的是传进来的component
        component.doSomething();    
    }
}
package com.designpatten.decorator;

public class concreteDecoratorA extends Decorator{

    public concreteDecoratorA(Component component) {
        super(component);
    }
    
    public void doSomething(){
        super.doSomething();
        this.doAnotherthing();
    }
    
    public void doAnotherthing(){
        System.out.println("新添加的功能C");
    }


}
package com.designpatten.decorator;

public class concreteDecoratorB extends Decorator {
    
    public concreteDecoratorB(Component component) {
        super(component);
    }
    public void doSomething(){
        super.doSomething();
        this.doAnotherthing();
    }
    
    public void doAnotherthing(){
        System.out.println("新添加的功能B");
    }

}
//最终的测试类
package com.designpatten.decorator;

public class decoratorTest {
    public static void main(String[] args) {
        //类似IO流的方式来定义 这里与IO过滤流的使用方式是一致的
        Component component1=new concreteDecoratorA(new concreteDecoratorB(new concreteComponent()));
        component1.doSomething();
        Component component2=new concreteDecoratorA(new concreteComponent());
        component2.doSomething();
        Component component3=new concreteDecoratorB(new concreteComponent());
        component3.doSomething();
    }

}

//输出结果
/*
功能A
新添加的功能B
新添加的功能C
功能A
新添加的功能C
功能A
新添加的功能B
*/

定义:

     所谓装饰类就是把客户端的调用委派到被装饰类中,装饰模式的关键是在于这种扩展是一种完全透明的方式。比如某种装饰的方式:

Component component2=new concreteDecoratorA(new concreteComponent());

component2.doSomething();

    调用component2的doSomthing方法,首先是调用其父类(concreteComponent)的doSomething方法,这个是最初版本的doSomething方法,之后再调用扩展的方法(这里有个递归的含义在里面 多层乞嵌套的时候 super.dosomthing()会一直向上递归 直到最初定义的dosomthing()方法),这样就实现了功能的扩展,由于各个concreteComponnet类都是继承component接口,这种扩展可以以嵌套的方式多层地进行。装饰模式可以在不必改变原来类文件和使用继承的情况下,动态地扩展一个对象的功能,他是通过创建一个包装对象用于包裹真实的对象。

特点:

1、 装饰模式以对客户端透明的方式来扩展对象的功能,是继承方式的一种替代方案

2、 装饰模式以对客户透明的方式动态地给对象附加更多的责任,换言之,客户端并不会觉得对象在装饰前与装饰之后有什么不同。

3、 可以在不创建更多类的前提下,将对象的功能进行扩展。

    就像在IO中 BufferInputstream DataInputstream FileInputstream三个类可以进行组合,但是并没有增加类的数目。比如上面的例子,通过基本的三个类,可以组合出实现功能A 功能B 功能C 以及分别实现功能A 功能C 和功能A和功能B 等等,不同的功能,但是最后并没有增加新的类,仅仅是通过对原有的几个类进行组合而完成的。

可以看出来几个基本的角色(对应IO来说):

1、 抽象的构建角色(Component)给出了一个抽象的接口,用来规范准备接收的附加责任对象。

2、 具体构建角色(concreteComponent)

3、 装饰角色(Decorator)持有一个构建对象的引用作为属性,并定义一个与抽象构建接口一致的接口,注意:装饰角色会实现抽象构建角色的接口,通过构造函数传递一个具体的构建角色进来。

4、 具体装饰角色(concreteDecorator)负责给构建角色贴上附加功能。

装饰模式与代理模式的区别:

    其实,它们的着重点一个在于“增加”职责(装饰者模式),另一个在于“控制”访问(代理模式)。这是它们最本质的区别。使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造,可以灵活地以不同的方式进行组合,具体的区别可以参考:

http://hi.baidu.com/springlie/item/834cb0e3fa778db52e140b48

http://www.cnblogs.com/jaredlam/archive/2011/11/08/2241089.html

    代理模式无法嵌套调用

    代理模式主要体现在对代理的对象施加控制,并不提供对象本身的增强功能,也就是说在代理模式下,那个先前的预处理的部分,可以修改成为权限控制的模块,如果当前传入进来的类的实例权限不够,就无法往下走,去访问被代理的对象的核心的方法。

    在网上找了一些相关的信息 貌似是这个样子:

    貌似是实现的机制很类似,特别是静态代理与装饰模式,但是它们最终的功能还是相反的。一个是增加功能,一个是权限限制。一说权限判断,就指的是代理模式,一说添加功能,就指得是装饰模式,虽然实现上两者确实很类似,差别主要是意图上的。

装饰模式与继承的区别:

1、继承是用来扩展一类对象的功能,需要子类,是静态的,在编译的时候才分配具体的职责,这样会导致很多的子类产生,比较缺乏灵活性。

2、装饰模式是用来扩展特定对象的功能,并不需要生成新的子类,并且是动态进行的,只需要对已有的对象进行不同的组合,在运行的时候才分配职责,这样可以防止子类过多导致的混乱,并且更加灵活,对与一个给定的对象,可以同时被不同的包装类进行包装。

3、装饰者模式可以动态地给一个对象增加其他职责。就扩展对象功能来说,装饰者模式比通过继承来生成子类更为灵活。所谓动态是说可以在系统运行时(RunTime)动态给对象增加其它职责而不需要修改代码或重新编译;所谓静态是说必须通过调整代码(DesignTime)才能给对象增加职责,而且系统还需要重新编译。

原文地址:https://www.cnblogs.com/Goden/p/3901664.html