java设计模式-装饰模式

来源:互联网 发布:淘宝交易快照怎么看 编辑:程序博客网 时间:2024/06/07 02:45

定义:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

1,不改变原类文件。

2,不使用继承。

3,动态扩展。


装饰者模式中的4个角色

  (1)被装饰者抽象Component:是一个接口或者抽象类,定义最核心的对象,这个类是装饰者的基类,例如Tea接口

  (2)被装饰者具体实现ConcreteComponent:这是Component接口或抽象类的实现,例如本例中的SuperTea

  (3)装饰者Decorator:一般是抽象类,实现Component,它里面必然有一个指向Component的引用,例如本例中AbstractTea

  (4)装饰者实现ConcreteDecorator1和ConcreteDecorator2:用来装饰最基本的类,如本例中的RedTea

example

被装饰抽象:

/** * Description:茶的基类(组件) * User: lc * Date: 2017/9/29 0029 * Time: 下午 1:28 */public interface Tea {    /**     * 成分     */    String hasMaterial();    /**     * 价格     *     * @return     */    BigDecimal cost();}

被装饰者具体实现:

/** * Description:茶的鼻祖实现(主实现) * User: lc * Date: 2017/9/30 0030 * Time: 下午 1:07 */public class SuperTea implements Tea {    @Override    public String hasMaterial() {        return "白开水";    }    @Override    public BigDecimal cost() {        return BigDecimal.ONE;    }}

装饰者:

/** * Description:抽象组件 * User: lc * Date: 2017/9/30 0030 * Time: 下午 1:10 */public abstract class AbstractTea implements Tea {    private Tea tea;    public AbstractTea(Tea tea) {        this.tea = tea;    }    public String hasMaterial() {        return this.tea.hasMaterial();    }    ;    public BigDecimal cost() {        return this.tea.cost();    }}

装饰者实现:

/** * Description:红茶 * User: lc * Date: 2017/9/30 0030 * Time: 下午 1:14 */public class ReadTea extends AbstractTea {    public ReadTea(Tea tea) {        super(tea);    }    /**     * 返回红茶组成成分     *     * @return     */    @Override    public String hasMaterial() {        return "red茶叶、" + super.hasMaterial();    }    /**     * 返回红茶的价格     *     * @return     */    @Override    public BigDecimal cost() {        return new BigDecimal(3.0).add(super.cost());   }
}


装饰者实现:

/** * Description:绿茶 * User: lc * Date: 2017/9/30 0030 * Time: 下午 1:28 */public class GreenTea extends AbstractTea {    public GreenTea(Tea tea) {        super(tea);    }    /**     * 返回绿茶组成成分     *     * @return     */    @Override    public String hasMaterial() {        return "green茶叶、" + super.hasMaterial();    }    /**     * 返回绿茶的价格     *     * @return     */    @Override    public BigDecimal cost() {        return new BigDecimal(4.0).add(super.cost());    }}

测试:

/** * Description: * User: lc * Date: 2017/9/30 0030 * Time: 下午 1:30 */public class Test {    public static void main(String[] args) {        System.out.println("客官:老板来一杯茶。。。。。。");        Tea superTea=new SuperTea();        System.out.println("老板:好嘞,客官。茶成分:"+superTea.hasMaterial()+"--价格:"+superTea.cost()+"元");        System.out.println("客官:老板茶没味道。来杯红茶");        AbstractTea abstractTea=null;         abstractTea=new ReadTea(superTea);        System.out.println("老板:好嘞,客官。红茶成分:"+abstractTea.hasMaterial()+"--价格:"+abstractTea.cost()+"元");        System.out.println("客官:老板有么有别的茶?");        System.out.println("老板:还有绿茶?");         abstractTea=new GreenTea(superTea);        System.out.println("老板:好嘞,客官。绿茶成分:"+abstractTea.hasMaterial()+"--价格:"+abstractTea.cost()+"元");        System.out.println("客官:老板有没有绿红茶?");        System.out.println("老板:你确定要?");        abstractTea=new ReadTea(abstractTea);        System.out.println("老板:好嘞,客官。绿红茶成分:"+abstractTea.hasMaterial()+"--价格:"+abstractTea.cost()+"元");    }}

结果:

客官:老板来一杯茶。。。。。。
老板:好嘞,客官。茶成分:白开水--价格:1元
客官:老板茶没味道。来杯红茶
老板:好嘞,客官。红茶成分:red茶叶、白开水--价格:4元
客官:老板有么有别的茶?
老板:还有绿茶?
老板:好嘞,客官。绿茶成分:green茶叶、白开水--价格:5元
客官:老板有没有绿红茶?
老板:你确定要?
老板:好嘞,客官。绿红茶成分:red茶叶、green茶叶、白开水--价格:8元

  

总结:

聪明的你,可能已经发现 就2个装饰者实现类,但是老板可以制定出3种茶。就我自己的理解 装饰者模式:就是修饰某个组件。比如本文章的例子Tea/superTea 是主题,而abstractTea以及具体的实现都是,封装了一些的装饰物品。比如随着老板生意越做越好,可能会添加很多种茶,甚至在原有的茶基础上添加一些配料。比如说红茶 (以后可能会出大杯、中杯、小杯等)。


结论:

1.装饰者类要实现真实类同样的接口(abstractTea实现Tea)

2.装饰者类内有一个真实对象的引用(可以通过装饰者类的构造器传入)(abstractTea引用了Tea)

3.装饰类对象在主类中接受请求,将请求发送给真实的对象(相当于已经将引用传递到了装饰类的真实对象)

4.装饰者可以在传入真实对象后,增加一些附加功能(因为装饰对象和真实对象都有同样的方法,装饰对象可以添加一定操作在调用真实对象的方法,或者先调用真实对象的方法,再

添加自己的方法)

5.不用继承,


优点:

 复用现有的代码(红绿茶就复用了绿茶以及红茶的代码),增强原有的组件的功能


缺点:

1.衍生出一些列的小对象,导致错中复杂


现成例子:JDK中的装饰者模式

 java.io中很多使用了装饰者模式
举个例子:FilterInputStream继承(实现)了InputStream,同时,BufferedInputStream继承了FilterInputStream,
1,被装饰者抽象组件:即最顶层的基类InputStream
2.被装饰者具体实现ConcreteComponent:FileInputStream和FileOutputStream就是它的实现
3.装饰者Decorator:FilterInputStream中有一个InputStream的实例和构造方法传入InputStream对象
    protected volatile InputStream in;  
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }  
4.装饰者实现:在   BufferedInputStream  中有构造方法传入InputStream对象,实现了装饰
    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }  


原创粉丝点击