zoukankan      html  css  js  c++  java
  • 大话--装饰者模式

    装饰者模式

    定义

     在不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的替代方案。

    使用场景

     扩展一个类的功能或给一个类添加附加职责,动态地给一个对象添加功能,这些功能可以再动态撤销。

    优点

     装饰类和被装饰类可以独立发展,不会互相耦合。装饰者模式是继承的一个替代模式

    通过使用不同的装饰类以及装饰类的排列组合,可以实现不同的效果。

    符合开闭原则(OCP):对扩展开放,对修改关闭。  符合多用组合,少用继承原则

    缺点

     多层装饰代码较复杂

    组成

     组件(Component):每个组件可以单独使用,也可以被装饰者包起来使用。

    具体组件(ConcreteComponent):动态地加上新行为的对象,扩展自Component。

    装饰者(Decorator):每个装饰者都会包装一个组件,即每个装饰者有一个实例变量保存某个Component的引用。

    tips

     装饰者也要实现被装饰对象实现的接口,这样才能使用多态的方法面向接口编程。在被装饰之后依旧返回一个接口引用,使其他类感知不到我们装饰者的存在。

    关键代码

     1.Component类充当抽象角色,不应该具体实现。

    2.修饰类引用和继承Component类,具体扩展类重写父类方法。

    类图

     

    使用装饰者模式的源码

     

    具体实现

    星巴克咖啡订单项目( 咖啡馆):

    1) 咖啡种类/单品咖啡:Espresso(意大利浓咖啡 )、ShortBlack 、LongBlack( 美式咖啡 )、Decaf( 无因咖啡 )

    2) 调料: Milk、Soy(豆浆)、Chocolate

    3) 要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便,维护方便

    4)使用 OO 来计算不同种类咖啡的费用 : 客户可以点单品咖啡,也可以单品咖啡+调料组合 。

     1 package Decorator;
     2 
     3 /**
     4  * @title: Drink
     5  * @Author yzhengy
     6  * @Date: 2020/7/28 23:36
     7  * @Question: 饮料抽象类
     8  */
     9 public  abstract class Drink {
    10 
    11     public String des;
    12     private float price = 0.0f;
    13 
    14     public String getDes() {
    15         return des;
    16     }
    17 
    18     public void setDes(String des) {
    19         this.des = des;
    20     }
    21 
    22     public float getPrice() {
    23         return price;
    24     }
    25 
    26     public void setPrice(float price) {
    27         this.price = price;
    28     }
    29 
    30     //计算费用的抽象方法,需要子类实现
    31     public abstract float cost();
    32 }
     1 package Decorator;
     2 
     3 /**
     4  * @title: Coffee
     5  * @Author yzhengy
     6  * @Date: 2020/7/28 23:40
     7  * @Question: 缓冲层,由于ConcreteComponent类很多,将共有部分提取出来
     8  */
     9 public class Coffee extends Drink {
    10 
    11     @Override
    12     public float cost() {
    13         return super.getPrice();
    14     }
    15 }
     1 //具体的饮料
     2 public class Espresso extends Coffee {
     3 
     4     public Espresso(){
     5         setDes("意大利咖啡");
     6         setPrice(6.0f);
     7     }
     8 
     9 }
    10 
    11 public class LongBlack extends Coffee {
    12 
    13     public LongBlack() {
    14         setDes("美式咖啡");
    15         setPrice(5.0f);
    16     }
    17 }
    18 
    19 public class ShortBlack extends Coffee {
    20 
    21     public ShortBlack() {
    22         setDes("单品咖啡");
    23         setPrice(4.0f);
    24     }
    25 }
     1 package Decorator;
     2 
     3 /**
     4  * @title: Decorator
     5  * @Author yzhengy
     6  * @Date: 2020/7/28 23:45
     7  * @Question: 装饰者对象
     8  */
     9 public class Decorator extends Drink {
    10 
    11     private Drink obj;
    12 
    13     public Decorator(Drink obj) {//组合关系
    14         this.obj = obj;
    15     }
    16 
    17     @Override
    18     public float cost() {
    19         return super.getPrice() + obj.cost();//小料自己的价格+单杯咖啡的价格
    20     }
    21 
    22     //obj.getDes():输出被装饰者的信息
    23     @Override
    24     public String getDes() {
    25         return super.des + " "+super.getPrice() + "&&" + obj.getDes();
    26     }
    27 }
     1 //调料类
     2 package Decorator;
     3 
     4 /**
     5  * @title: Chocolate
     6  * @Author yzhengy
     7  * @Date: 2020/7/29 10:15
     8  * @Question: 具体的decorator ,此处指每一种小料
     9  */
    10 public class Chocolate extends Decorator {
    11 
    12     public Chocolate(Drink obj) {
    13         super(obj);//通过子类的构造方法去调用父类的构造方法.
    14         setDes("巧克力");
    15         setPrice(3.0f);
    16     }
    17 }
    18 
    19 public class Milk extends Decorator {
    20 
    21     public Milk(Drink obj) {
    22         super(obj);
    23         setDes("牛奶");
    24         setPrice(2.0f);
    25     }
    26 }
    27 
    28 public class Soy extends Decorator {
    29 
    30     public Soy(Drink obj) {
    31         super(obj);
    32         setDes("豆浆");
    33         setPrice(1.5f);
    34     }
    35 }
     1 package Decorator;
     2 
     3 /**
     4  * @title: CoffeeBar
     5  * @Author yzhengy
     6  * @Date: 2020/7/29 10:22
     7  * @Question: 装饰者模式下的订单:两份巧克力+一分牛奶+LongBlack
     8  */
     9 public class CoffeeBar {
    10 
    11     public static void main(String[] args) {
    12         //1.点一份LongBlack
    13         Drink order = new LongBlack();
    14         System.out.println("费用=" + order.cost());
    15         System.out.println("描述=" + order.getDes());
    16 
    17         //2.order加入一份牛奶
    18         order = new Milk(order);
    19         System.out.println("加入一份牛奶 费用=" + order.cost());
    20         System.out.println("加入一份牛奶 描述=" + order.getDes());
    21 
    22         //3.order加入一份巧克力
    23         order = new Chocolate(order);
    24         System.out.println("加入一份牛奶和一份巧克力 费用=" + order.cost());
    25         System.out.println("加入一份牛奶和一份巧克力 描述=" + order.getDes());
    26 
    27         //4.order再加入一份巧克力
    28         order = new Chocolate(order);
    29         System.out.println("加入一份牛奶和一份巧克力 费用=" + order.cost());
    30         System.out.println("加入一份牛奶和一份巧克力 描述=" + order.getDes());
    31 
    32         //新的订单
    33         Drink order2 = new Newcoffee();
    34         System.out.println("无因咖啡 费用=" + order2.cost());
    35         System.out.println("无因咖啡 描述=" + order2.getDes());
    36 
    37     }
    38 
    39 }

    如果需要新增加一种咖啡,则只需要增加该咖啡品种即可。

     1 package Decorator;
     2 
     3 /**
     4  * @title: Newcoffee
     5  * @Author yzhengy
     6  * @Date: 2020/7/29 11:19
     7  * @Question: 如果新增了一个咖啡品种
     8  */
     9 public class Newcoffee extends Coffee {
    10 
    11     public Newcoffee() {
    12         setDes("无因咖啡");
    13         setPrice(3.5f);
    14     }
    15 }
  • 相关阅读:
    oracle 使用正则表达式获取字符串中包含的数字
    oracle 将逗号分隔的字符串转成多行记录
    sqlplus下 查看oracle 执行计划
    使用connect by 虚拟生成100条记录
    Lomsat gelral
    Legacy
    慢慢变小的序列(好题)
    Walls(扫描线)
    线段树求面积并,面积交,周长
    最小圆覆盖(随机增量||模拟退火)
  • 原文地址:https://www.cnblogs.com/yzhengy/p/13398046.html
Copyright © 2011-2022 走看看