装饰着模式(Decorator Pattern)

  装饰者模式是动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

  简单的说,装饰者模式由三部分组成,分别是基础抽象类,可以被装饰者包装的类、装饰者类,后两种类均是基础抽象类的子类,但是里面的方法对于基础类有更多的扩展,最终使用,均是使用的基础类进行操作,因此,无论怎么包装,出来的对象都可以使用基础类接收。同时,可以被装饰者包装的类一般使用无参构造,而装饰者类则是使用基础类作为入参的构造函数。

  举个例子,一杯咖啡,他的名字和售价,就可能因为添加不同的调料而导致售价和名称不同,并且调料的组合方式也存在多种。

  在JDK中,I/O就是使用的装饰着模式,如下图所示,InputStrem是装饰者模式的抽象组件,红色标记的4个是可以被装饰者包起来的具体组件,而绿色部分,就是具体的装饰者。

  试用装饰者模式有一个缺点,就是代码中会存在大量的小类,可能会给使用API人造成困扰。

  

 

   那么,就根据上述举的例子,来写一下装饰者模式

  首先,创建一个抽象类,抽象类中包含一个获取名称的方法和一个获取价格的抽象方法

package lcl.mm.pattern.decorator;

public abstract class Beverage {
    String desc = "Unknow Beverge";
    public String getDesc(){
        return desc;
    }

    public abstract int cost();
}

  然后,分别创建两个可以被装饰者包装的A咖啡类和B咖啡类,类中一个无参构造函数和一个获取价格的函数,无参构造函数中直接返回咖啡的名称,而价格直接返回自身的价格。

package lcl.mm.pattern.decorator;

public class CofeeA extends Beverage{
    public CofeeA(){
        desc = "CofeeA";
    }

    @Override
    public int cost() {
        return 5;
    }
}
package lcl.mm.pattern.decorator;

public class CofeeB extends Beverage{
    public CofeeB(){
        desc = "CofeeB";
    }

    @Override
    public int cost() {
        return 10;
    }
}

接下来就创建两个装饰者类调味料A和调味料B,类中包含有参构造函数、获取名称方法和获取售价方法,在构造函数中,将Beverage传入,获取名称时,在原有Beverage的名称上加上该调味料的名称,而获取价格的方法是在原有Beverage的售价上加上该调味料的价格、

package lcl.mm.pattern.decorator;

public class CondimentA extends Beverage {
    Beverage beverage;
    public CondimentA(Beverage beverage){
        this.beverage = beverage;
    }
    public String getDesc(){
        return beverage.getDesc() + ",加调味料CondimentA";
    }

    @Override
    public int cost() {
        return 2 + beverage.cost();
    }
}
package lcl.mm.pattern.decorator;

public class CondimentB extends Beverage {
    Beverage beverage;
    public CondimentB(Beverage beverage){
        this.beverage = beverage;
    }
    public String getDesc(){
        return beverage.getDesc() + ",加调味料CondimentB";
    }

    @Override
    public int cost() {
        return 1 + beverage.cost();
    }
}

如上,装饰者模式就写完了,接下来进行测试:

    @Test
    public void decoretorTest(){
        Beverage beverage1 = new CofeeA();
        log.info("Beverage=={}售价:${}",beverage1.getDesc(),beverage1.cost());
        Beverage beverage = new CofeeB();
        log.info("Beverage=={}售价:${}",beverage.getDesc(),beverage.cost());
        beverage = new CondimentA(beverage);
        log.info("Beverage=={}售价:${}",beverage.getDesc(),beverage.cost());
        beverage = new CondimentB(beverage);
        log.info("Beverage=={}售价:${}",beverage.getDesc(),beverage.cost());
        beverage = new CondimentA(beverage);
        log.info("Beverage=={}售价:${}",beverage.getDesc(),beverage.cost());
    }

输出:

 

posted @ 2020-07-02 22:25  李聪龙  阅读(232)  评论(0编辑  收藏  举报