• 装饰者模式


    场景:

    购买咖啡时,可以要求加入各种调料,例如,豆浆,摩卡

    豆浆,摩卡就是装饰者,咖啡是被装饰者。

    不好的设计:

    问题:

    1、一旦出现新的调料,我们就需要加上新的方法,并改变超类中的cost方法

    2、以后可能开发新的饮料,对这些饮料(冰茶),某些调料可能并不合适,但是在这个设计中,Tea子类

    仍将继承那些不合法的方法,例如 奶泡。

    3、万一顾客想要双倍摩卡,怎么办?

    装饰者和被装饰者必须是一样的类型,也就是有共同的超类,这是相当关键的地方。
    在这里,我们利用继承达到“类型匹配”,而不是利用继承获得“行为”。

    当我们将装饰者与组件组合时,就是在加入新的行为,所得到的新行为,并不是继承自
    超类,而是由组合对象而来。

    我们可以在任何时候,实现新的装饰者增加新的行为。如果依赖继承,每当需要新行为时,
    还得修改现有的代码。

    类图:

    //超类(抽象组件)

    public abstract class Beverage{

      String description = "Unknown Beverage";

       public String getDescription()

      {

        return description;

      }

      public abstract double cost();

    }

    //抽象装饰者(调料)

    public abstract class CondimentDecorator extends Beverage{

      public abstract  String getDescription();

    }

    //饮料(具体组件)

    public class Espresso extends Beverage{

       public Espresso ()

      {

        description = "Espresso";

      }

      public double cost()

      {

        return 1.99;

      }

    }

    //调料(具体装饰者)

    public class Mocha extends CondimentDecorator {

      Beverage beverage;//用一个实例变量记录饮料,也就是被装饰者

       public Mocha (Beverage beverage )

      {

        this.beverage = beverage;

      }

      public String getDescription()

      {

        return beverage.getDescription() + ", Mocha";

      }

      public double cost()

      {

        return 1.99 + beverage.cost();

      }

    }

    摩卡(Mocha)是一个装饰者,所以让它扩展自CondimentDecorator 

    CondimentDecorator 扩展自Beverage 

    ----------------------------------------------------------------------------

    测试代码

    public static void main(String[] args)

    {

      Beverage  beverage  =  new Espresso();//一杯espresso

      beverage  = new  Mocha(beverage); //加入调料摩卡

      beverage  = new  Mocha(beverage); //再加入一份摩卡

      //加了两份摩卡的espresso的价格

      double price = beverage .cost();

    }

    要点:

    在我们的设计中,应该允许行为可以被扩展,而无须修改现有的代码。

    装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得复杂。

    在选择需要被扩展的代码部分时要小心。每个地方都采用开发-关闭原则,是一种浪费,

    也没必要,还会导致代码变得复杂且难以理解。

  • 相关阅读:
    什么是Spring的IOC和DI
    2021年ACP考试复习笔记-云服务器ECS知识点及练习
    个人站点搭建完成啦,欢迎前来参观~
    准备一台标准服务器(模版机)!
    正则表达式几个常用的特殊字符!
    Shell的几个重点工具
    Shell入门,关于语法的一些简单玩意儿
    Mysql for Linux的安装以及远程访问
    在学到MySQL索引时,涉及到了B树和B+树.聊一聊
    Linux的一些问题的处理(重要目录,/配置静态IP/主机名/hosts映射)
  • 原文地址:https://www.cnblogs.com/zhangxuan/p/8350643.html
Copyright © 2020-2023  润新知