装饰者模式——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 abstract string GetDescription();
    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);
时间: 2024-10-25 14:01:49

装饰者模式——HeadFirst 设计模式学习笔记的相关文章

桥接模式——HeadFirst设计模式学习笔记

桥接模式:将抽象部分与实现部分分离,使它们都可以独立的变化. 优点: 将抽象与实现解耦,可以独立拓展而不影响对方 处理多维度变化的场景,将各个维度设计成独立的继承结构.使各个维度可以独立的扩展在抽象层建立联系. 使用"对象间的组合关系"解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化. 缺点: 增加了代码的复杂度 桥接模式vs装饰者模式: 均减少了子类的数目,避免了复杂的继承出现 装饰者的目的是添加新功能,桥接模式为了满足多维度的变化 举例: http://w

代理模式——HeadFirst设计模式学习笔记

代理模式:为另一个对象提供一个替身或占位符控制这个对象的访问 特点: 让代理对象控制对象的访问,被代理对象可以是远程对象(远程代理),创建开销较大对象(虚拟代理),或需要安全控制的对象(保护代理) 代理分类: 远程代理:好比远程对象(在不同JVM虚拟机的对象)的本地代表(本地方法的行为转移到远程),帮助我们处理网络上的细节 代理假装自己是远程对象,不过只是一个中间角色,处理访问远程对象 Java RMI提供了客户辅助对象stub和服务辅助对象skeleton,并为其提供相同的方法 注意方法返回值

原型模式——HeadFirst设计模式学习笔记

原型模式:通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的(clone) 特点: 向用户隐藏了创建新实例的复杂性 让用户可以产生未知类型的对象,即只需知道对象实现了哪些接口,而无需知道具体是哪种实现 在某些情况下,复制对象比创建对象更高效 Prototype类需要具备以下两个条件: 实现Cloneable接口.在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone

状态模式——HeadFirst设计模式学习笔记

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类 --将状态封装成独立的类,将动作委托给当前状态对象,所以行为会随着内部状态的变化而变化 状态转换图:为每一个状态创建一个实现一组相同操作接口的对象,实体对象包含所有状态并有一个当前状态接口的引用 特点: 允许一个对象基于不用的状态有不同的行为 把变化的东西取出来,局部化每个状态的行为,每个状态的行为局部化到自己的类中,遵守"封装变化"原则,减少了繁琐的if语句,满足"对修改关闭,对扩展开放"

策略模式——HeadFirst 设计模式学习笔记

策略模式:策略模式定义了算法族,分别封装起来,让他们可以相互替换,此模式让算法的变化独立于使用算法的客户. 设计原则: 找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起.以便以后轻松的更改或扩充此部分,而不影响不需要变化的其他部分 针对接口编程而不是针对实现编程.实际的实现不会被绑定,调用时只知道调用的接口,而无需知道具体的实现方式 多用组合,少用继承.使用组合有很大的弹性,可以在运行时动态改变行为 要点: 良好的OO设计必须遵循可复用,可拓展,可维护 大部分模式允

中介者模式——HeadFirst设计模式学习笔记

中介者模式:集中管理相关对象之间的复杂沟通和控制     ------>>>>    特点: 关系复杂的对象之间解耦了(对象之间必须相互认识 -> 对象只认识中介者) 中介者包含了整个系统的控制逻辑,控制逻辑集中可以简化维护 每个对象在自己状态改变时告诉中介者,每个对象对中介者发出的请求给予回应 中介者常常被用来协调GUI组建 中介者需要包含所有被中介对象的引用,被中介对象可以选择是否包含中介者引用(可以在方法调用时传入) 缺点: 中介者自身可能过于复杂

解释器模式——HeadFirst设计模式学习笔记

解释器模式:给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子 特点: 每一种语法设置为一个类,便于实现 便于扩展语言的语法 用与处理重复发生的交叉问题或解析一种语言 缺点: 解释器模式会引起类膨胀 效率不高 解释器模式采用递归调用方法 举例: 1 //解释器接口 2 public interface Expression { 3 public boolean interpret(String context); 4 } 5 6 //实现Or解释器 7 p

生成器模式——HeadFirst设计模式学习笔记

生成器模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 builder:为创建一个产品对象的各个部件指定抽象接口 ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个产品的引用 Director:构造一个使用Builder接口的对象(可选) Product:表示被构造的复杂对象 优点: 将一个复杂对象的创建过程封装起来 允许对象通过多个步骤来创建,并且可以改变过程(这和只有一个步骤的工厂模式不同)

组合模式——HeadFirst设计模式学习笔记

组合模式:允许将对象组合成树形结构来表现"整体/部分"层次结构.组合让客户用一致的方式处理个别对象和组合对象 特点: 树形结构表示对象组合 忽略对象组合和对象个体之间的差别,即相同的操作既可以作用于对象组合,也可以作用与对象个体 注意: 因为继承方法中,有些方法只有对叶子节点有意义,而有些方法只对非叶子节点有意义,我们可以将基类的方法默认实现为抛出UnsupportedOperationException,如果方法无意义,则无需修改默认继承就可以了 透明性: 组合模式以单一责任原则换取