设计模式之装饰者模式

  装饰者(Decorator)模式就是在不修改任何底层代码的状况下,给对象赋予新的职责编程

  装饰者模式又称包装模式,即:在真实对象的外层包装一层层新的职能。设计模式

  装饰者模式主要采用组合的方式拓展对象的行为,是给爱用继承的人一个全新的设计眼界。(继承是在编译时静态决定对象的行为,而组合是在运行时动态地扩展对象的行为。)架构

  须要格外注意的是:装饰者与被装饰者必须是同一个类型,即:具备相同的超类。【这里经过继承实现类型匹配】ide

  装饰者模式包含四个角色:抽象目标组件,具体目标组件,抽象装饰者,具体装饰者。其中,目标组件就是须要被装饰的对象。优化

 

1.抽象目标组件(Component)this

  目标组件的抽象类,是全部装饰者与具体组件的超类。这是为了保持组件被装饰后,返回的对象类型保持不变spa

public abstract class Beverage {

    protected String description = "Unknown Beverage";

    public String getDescription() {
        return description;
    }

    public abstract BigDecimal cost();
}

 

2.具体目标组件设计

  须要赋予新权限的组件。3d

public class DarkRoast extends Beverage{

    public DarkRoast() {
        description = "Dark Roast";
    }
    
    @Override
    public BigDecimal cost() {
//定义深焙饮料的价格
return new BigDecimal(0.25); } }

 

3.抽象装饰者code

//须要在饮料中添加的调味品
//具备两个抽象方法:getDescription()、cost()
public
abstract class Condiment extends Beverage { public abstract String getDescription(); }

 

4.具体装饰者

public class Mocha extends Condiment{

    private Beverage beverage;
    
    public Mocha(Beverage beverage) {
        super();
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
     //在原有饮料的描述中增添添加剂的描述
return beverage.getDescription() + ", Mocha"; } @Override public BigDecimal cost() {
//返回饮料加上添加剂的总价。0.6是摩卡添加剂的价格
return new BigDecimal(0.6).add(beverage.cost()).setScale(2, BigDecimal.ROUND_HALF_UP); } }
public class Whip extends Condiment{

    private Beverage beverage;
    
    public Whip(Beverage beverage) {
        super();
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return  beverage.getDescription() + ", Whip";
    }

    @Override
    public BigDecimal cost() {
        return new BigDecimal(0.5).add(beverage.cost()).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

}

 

5.Demo

public class BeverageDemo {

    public static void main(String[] args) {
        Beverage beverage = new DarkRoast();
        System.out.println(beverage.getDescription() +" : " + beverage.cost());
        
        
        //use mocha & whip to decorate dark-roast.
        beverage = new Mocha(beverage);
        beverage = new Whip(beverage);
        System.out.println(beverage.getDescription() +" : " + beverage.cost());
        /*Log:
         * Dark Roast : 0.25
         * Dark Roast, Mocha, Whip : 1.35*/
    }
}

 

6.备注

  装饰模式是 针对抽象组件(Component)类型编程。可是,若是你要针对具体组件编程时,就应该从新思考你的应用架构,以及装饰者是否合适。固然也能够改变Component接口,增长新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要作出最佳选择。
 
     装饰模式会致使设计中出现许多小类,若是过分使用,会使程序变得很复杂。【能够经过工厂模式和生成器模式进行优化】
 
7.拓展
    7.1  若是只有一个Concrete Component类而没有抽象的Component接口时,可让Decorator继承Concrete Component。
    7.2  若是只有一个Concrete Decorator类时,能够将Decorator和Concrete Decorator合并。
 
8.使用场景
    8.1 须要 扩展一个类的功能,或给一个类添加附加职责。
    8.2 须要动态的 给一个对象添加功能,这些功能能够再动态的撤销。
    8.3 须要 增长由一些基本功能的排列组合而产生的很是大量的功能,从而使继承关系变的不现实。
    8.4 当不能采用生成子类的方法进行扩充时。一种状况是,可能 有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增加。另外一种状况多是由于 类定义被隐藏,或类定义不能用于生成子类
 

9. 补充

  Java I/O是装饰者模式的典型例子。

 

10. 参考资料

    10.1 O'Reilly:《Head First设计模式》

    10.2 百度百科 : 《装饰者模式》

相关文章
相关标签/搜索