设计模式--装饰者模式

装饰者模式:

  装饰者模式动态的将责任附加到对象身上,若要拓展功能,装饰者提供了一种比继承更好的解决方案.

  装饰者和被装饰对象都拥有相同的超类型.

  你可以用一个或多个装饰者包装一个对象.

  既然装饰者和被装饰对象都拥有相同的超类型,所以在任何需要原始对象(被包装的)的场合,都可以使用装饰过的对象代替他.

  装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的.

  对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用你需要得装饰者来装使对象.

  装饰者模式可以很好的做到开闭原则,即类应该对扩展开放,对修改关闭.

  装饰者模式解决的问题通常也可以通过大量的继承来实现,但后者这样不仅是代码很冗余,而且利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为,然而,如果使用组合的方式扩展对象的行为,就可以在运行时动态的指定它,即是我们最终总结出来的装饰着模式.

模拟案例:

  饮品店卖饮料,假设会卖咖啡和牛奶,而顾客可以选择加冰或者加摩卡,每一个饮料是一个价格,加冰或者摩卡需要另外多付一些钱,这时就可能出现"加冰咖啡","加冰牛奶","加摩卡咖啡","加摩卡牛奶",甚至还有"既加冰又加摩卡的咖啡","既加冰又加摩卡的牛奶",甚至甚至还有"加两份冰一份摩卡的咖啡",这样的话,如果再多几种饮料,再多几种调料,那么子类是无穷的,使用继承的方式,会把人累死的,所以,我们来使用装饰者模式来实现:

抽象类Beverage(饮料):该类是所有类的超类

package com.wang.decotate;

public abstract class Beverage {
        //饮料名
     String name;
    //价格
    public abstract double cost();
    //描述一下饮料
    public String getName() {
        return name;
    }
}

抽象类Decorator,继承自Beverage类:

package com.wang.decotate;

public abstract class Decorator extends Beverage {

    public abstract double cost();

}

第一种饮料咖啡,子类Coffer:

package com.wang.decotate;

public class Coffer extends Beverage {

    public Coffer(){
        name="咖啡";
    }
    
    @Override
    public double cost() {
        return 7.00;
    }

}

第二种饮料牛奶,子类Milk:

package com.wang.decotate;

public class Milk extends Beverage {

    public Milk(){
        name="牛奶";
    }
    
    @Override
    public double cost() {
        return 9.80;
    }

}

第一种调料 冰块,子类Ice:

package com.wang.decotate;

public class Ice extends Decorator {
    
    Beverage b;
    
    public Ice(Beverage b) {
        this.b = b;
    }

    @Override
    public String getName() {
        return b.getName()+"冰块";
    }
    

    @Override
    public double cost() {
        return b.cost()+1.22;
    }

}

第二种调料 摩卡,子类Mocha:

package com.wang.decotate;

public class Mocha extends Decorator {

    Beverage b;
    public Mocha(Beverage b) {
        this.b = b;
    }

    @Override
    public String getName() {
        return b.getName()+"摩卡";
    }
    

    @Override
    public double cost() {
        return b.cost()+2.00;
    }

}

测试类Test:

package com.wang.decotate;

public class Test1 {

    public static void main(String[] args) {
        //顾客1:买一份什么都不加的咖啡
        Beverage b1=new Coffer();
        System.out.println("纯咖啡的价格:"+b1.cost());
        //顾客2:买一份加冰的咖啡
        Beverage b2=new Coffer();
        b2=new Ice(b2);
        System.out.println("加冰的咖啡价格:"+b2.cost());
        //顾客3:买一份加一份冰两份摩卡的咖啡
        Beverage b3=new Coffer();
        b3=new Ice(b3);
        b3=new Mocha(b3);
        b3=new Mocha(b3);
        System.out.println("加冰加摩卡的咖啡价格:"+b3.cost());
        //顾客4:买一份加冰加摩卡的咖啡,这次换一种写法,如下
        Beverage b4=new Mocha(new Ice(new Coffer()));
        System.out.println("加冰加摩卡的咖啡价格:"+b4.cost());
    }
}

打印结果:

纯咖啡的价格:7.0
加冰的咖啡价格:8.22
加冰加摩卡的咖啡价格:12.22
加冰加摩卡的咖啡价格:10.22

 

  看吧,这次不管客人要点什么样的饮料,都可以了,我们可以随意指定,这就是装饰者模式的强大之处.

posted @ 2016-05-08 23:30  冬至饮雪  阅读(209)  评论(0)    收藏  举报