zoukankan      html  css  js  c++  java
  • 设计模式之装饰者模式

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

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

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

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

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

    1.抽象目标组件(Component)

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

    public abstract class Beverage {
    
        protected String description = "Unknown Beverage";
    
        public String getDescription() {
            return description;
        }
    
        public abstract BigDecimal cost();
    }

    2.具体目标组件

      需要赋予新权限的组件。

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

    3.抽象装饰者

    //需要在饮料中添加的调味品
    //具有两个抽象方法: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 百度百科 : 《装饰者模式》

  • 相关阅读:
    sqlalchemy访问Oracle数据库报错:UnicodeDecodeError: 'big5' codec can't decode byte 0xfb in position 2: illegal multibyte sequence
    Mac如何安装FastDfs
    Django执行Sql语句笔记
    跑DRF框架分页源码笔记
    Python Paginator分页学习
    Python Excel笔记
    npm run dev报错解决方法
    npm install --global vue-cli 报错 [..................] / rollbackFailedOptional: verb npm-session abfa82f3041ebc02
    MS17_010漏洞攻击Windows7
    虚拟机启动黑屏
  • 原文地址:https://www.cnblogs.com/BlueStarWei/p/10515145.html
Copyright © 2011-2022 走看看