zoukankan      html  css  js  c++  java
  • 装饰者模式——HeadFirst 设计模式学习笔记

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

    设计原则:

    • 类的设计应该对拓展开放,对修改关闭。允许类容易拓展,在不修改现有代码的情况下添加新的行为

    特点:

    • 装饰者和被装饰对象有相同的超类型,我们利用继承达到“类型匹配”,而不是利用继承获得“行为”。
    • 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。如果依赖继承,那么类的行为只能在编译时静态决定,行为不是来自超类就是子类覆盖后的版本,每当需要新行为时,还得修改现有代码。如果利用组合,就可以动态的实现新的装饰者增加新的行为
    • 你可以用一个或多个装饰者包装一个对象
    • 既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它
    • 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的
    • 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象

    Java.io

    • java.io使用装饰者模式实现
    • 缺点:设计过程中产生大量的小类

    举例:

    • 由于StarBuzz咖啡连锁店业务扩张,准备更新订单系统,以合乎他们的饮料供应要求。基础咖啡的种类增加,而且咖啡中的添加物(如奶泡)增加,如果对没种咖啡配附加品建立一个类的话

    • 显然不显示,类的数量爆炸增长。那么如果基类Beverage增加一些判断所添加的调料种类的布尔类型的成员变量和各种调料的价格就好了,然后在不同的咖啡的实现类中的cost根据那些判断的成员变量就可以计算出总的价格了

    • 这样做,确实可以暂时满足需求,但是还会存在一些潜在的隐患,如

      l  调料价格变动会改变原有代码

      l  新增调料,除了加上新增方法外,还需要改变超类中的Cost()方法

      l  依赖继承,子类将继承一些对自身并不合适的方法

      l  部分需求无法满足:如双倍摩卡咖啡

      l  违反了开放—关闭原则

    • 使用装饰者模式修改设计
      • 装饰者和被装饰者都继承自Beverage类,也就是拥有共同的超类,利用继承达到“类型匹配”,而不是利用继承获得“行为”
      • 每个装饰者都有一个Beverage类对象的实例,记录所装饰的事物,用于保存引用并代表它
      • 装饰者可以填上新的方法,新行为是通过在旧行为前面或后面做一些计算添加的

    代码实现:

    • Beverage类(抽象组件)

    • 1     public abstract class Beverage
      2     {
      3         public string description = "Unknown Beverage";
      4         public string GetDescription(){ return description; };
      5         public abstract double Cost();
      6     }
    • Condiment(调料)基类(继承自Beverage基类,抽象装饰者)

    •     public abstract class CondimentDecorator extends Beverage
          {
              public  abstract string GetDescription();//必须由子类实现
          }
    • 饮料类(继承Beverage基类,具体组件)

    • public class Espresso extends Beverage
         {
             public Espresso()
             {
                 description = "Espresso";//设置饮料的表述,description继承自Beverage类的实例变量
             }
       
             public double Cost()
             {
                 return 1.99;
             }
       
             public string GetDescription()
             {
                 return description;
             }
         }
    • 调料类(装饰者)

    •  1 public class Mocha extends CondimentDecorator
       2     {
       3         Beverage beverage;
       4         public Mocha(Beverage beverage)
       5         {
       6             this.beverage = beverage;
       7         }
       8  
       9         public string GetDescription()
      10         {
      11             return beverage.GetDescription() + ",Mocha";
      12         }
      13         public double Cost()
      14         {
      15             return 0.2 + beverage.Cost();
      16         }
      17     }
    • 测试代码

    • 1 Beverage beverage1 = new DarkRoase();
      2 beverage1 = new Mocha(beverage1);
      3 beverage1 = new Mocha(beverage1);
      4 beverage1 = new Whip(beverage1);
  • 相关阅读:
    LeetCode(65):有效数字
    LeetCode(64):最小路径和
    物理Data Guard的日常维护
    Oracle Data Guard的配置
    SQL基础--完整性约束
    使用rman迁移数据库到异机
    Oracle的表空间和数据文件
    Oracle的控制文件
    Oracle重做日志文件
    RMAN的恢复篇
  • 原文地址:https://www.cnblogs.com/HectorHou/p/5979188.html
Copyright © 2011-2022 走看看