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

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

    对于我自己的理解:装饰者模式就是一个在继承层面上的递归。

    对于装饰者模式而言,有两个很重要的概念:component 与 decorator;

    component (组件):被装饰的主体

    decorator(装饰者):用于装饰主体的配件

    下面我们来用一个咖啡馆的订单系统作为实例。

    咖啡馆需求:根据客户的订单,生成价格。而客户可选择一个单品咖啡,并且可以在这个选择的单品咖啡上添加相应装饰(牛奶、奶泡、茶....etc)

    根据上面的需求,我们应用装饰者模式去实现。

    类图:

    装饰者模式

    注意:标准的装饰者模式是没有 coffeeComponent 这一层的~ 这里是为了实现更加便捷、清晰而添加上去的。

    代码实现:

    AbstractCoffeeComponent :component,被装饰的组件

     1 package decorator.component;
     2 
     3 /**
     4  * Created by chenjiayin on 2017/3/18.
     5  */
     6 public abstract class AbstractCoffeeComponent
     7 {
     8     public String description;
     9     private double price;
    10 
    11     public String getDescription()
    12     {
    13         return description + ":" + this.getPrice();
    14     }
    15 
    16     public void setDescription(String description)
    17     {
    18         this.description = description;
    19     }
    20 
    21     public double getPrice()
    22     {
    23         return price;
    24     }
    25 
    26     public void setPrice(double price)
    27     {
    28         this.price = price;
    29     }
    30 
    31     public abstract double cost();
    32 }

    CoffeeComponent :抽取这一层,cost()里面的价格就是它本身的价格,因为点单品只会点一个单品的。。。两个单品混合的咖啡不在本次需求的考虑范围内
     1 package decorator.component;
     2 
     3 /**
     4  * Created by chenjiayin on 2017/3/18.
     5  */
     6 public class CoffeeComponent extends AbstractCoffeeComponent
     7 {
     8     @Override
     9     public double cost()
    10     {
    11         return super.getPrice();
    12     }
    13 }

    单品咖啡,Decaf

     1 package decorator.component;
     2 
     3 /**
     4  * Created by chenjiayin on 2017/3/18.
     5  */
     6 public class Decaf extends CoffeeComponent
     7 {
     8     public Decaf()
     9     {
    10         super.setDescription("Decaf");
    11         super.setPrice(30);
    12     }
    13 }

    单品咖啡,Expresso

     1 package decorator.component;
     2 
     3 /**
     4  * Created by chenjiayin on 2017/3/18.
     5  */
     6 public class Expresso extends CoffeeComponent
     7 {
     8     public Expresso()
     9     {
    10         super.setDescription("Expresso");
    11         super.setPrice(31);
    12     }
    13 }

    单品咖啡,LongBlack

     1 package decorator.component;
     2 
     3 /**
     4  * Created by chenjiayin on 2017/3/18.
     5  */
     6 public class LongBlack extends CoffeeComponent
     7 {
     8     public LongBlack()
     9     {
    10         super.setDescription("LongBlack");
    11         super.setPrice(32);
    12     }
    13 }

    单品咖啡,ShortBlack

     1 package decorator.component;
     2 
     3 /**
     4  * Created by chenjiayin on 2017/3/18.
     5  */
     6 public class ShortBlack extends CoffeeComponent
     7 {
     8     public ShortBlack()
     9     {
    10         super.setDescription("ShortBlack");
    11         super.setPrice(33);
    12     }
    13 }

    好了,上面,我们已经将我们需要的组件都已经定义好了,下面,我们开始定义装饰者了。

    AbstractCoffeeDecorator:装饰者的抽象类,继承了组件,并且以组件作为它的一属性,因为需要装饰它。

     1 package decorator.decorator;
     2 
     3 import decorator.component.AbstractCoffeeComponent;
     4 
     5 /**
     6  * Created by chenjiayin on 2017/3/18.
     7  */
     8 public abstract class AbstractCoffeeDecorator extends AbstractCoffeeComponent
     9 {
    10     private AbstractCoffeeComponent coffeeComponent;
    11 
    12     public AbstractCoffeeDecorator(AbstractCoffeeComponent coffeeComponent)
    13     {
    14         this.coffeeComponent = coffeeComponent;
    15     }
    16 
    17     @Override
    18     public double cost()
    19     {
    20         return super.getPrice() + coffeeComponent.cost();
    21     }
    22 
    23     @Override
    24     public String getDescription()
    25     {
    26         return super.getDescription() + "+" + coffeeComponent.getDescription();
    27     }
    28 }

    装饰者,Milk

     1 package decorator.decorator;
     2 
     3 import decorator.component.AbstractCoffeeComponent;
     4 
     5 /**
     6  * Created by chenjiayin on 2017/3/18.
     7  */
     8 public class Milk extends AbstractCoffeeDecorator
     9 {
    10     public Milk(AbstractCoffeeComponent coffeeComponent)
    11     {
    12         super(coffeeComponent);
    13         super.setDescription("Milk");
    14         super.setPrice(5);
    15     }
    16 }

    装饰者,Whip

     1 package decorator.decorator;
     2 
     3 import decorator.component.AbstractCoffeeComponent;
     4 
     5 /**
     6  * Created by chenjiayin on 2017/3/18.
     7  */
     8 public class Whip extends AbstractCoffeeDecorator
     9 {
    10     public Whip(AbstractCoffeeComponent coffeeComponent)
    11     {
    12         super(coffeeComponent);
    13         super.setDescription("Whip");
    14         super.setPrice(3);
    15     }
    16 }

    装饰者,Tea

     1 package decorator.decorator;
     2 
     3 import decorator.component.AbstractCoffeeComponent;
     4 
     5 /**
     6  * Created by chenjiayin on 2017/3/18.
     7  */
     8 public class Tea extends AbstractCoffeeDecorator
     9 {
    10     public Tea(AbstractCoffeeComponent coffeeComponent)
    11     {
    12         super(coffeeComponent);
    13         super.setDescription("Tea");
    14         super.setPrice(10);
    15     }
    16 }

    我们的装饰者,与我们的组件都已经定义好了,我们来看一下成果。

    测试类,DecoratorMain

     1 package decorator;
     2 
     3 import decorator.component.AbstractCoffeeComponent;
     4 import decorator.component.Decaf;
     5 import decorator.component.Expresso;
     6 import decorator.decorator.Milk;
     7 import decorator.decorator.Tea;
     8 import decorator.decorator.Whip;
     9 
    10 /**
    11  * Created by chenjiayin on 2017/3/18.
    12  */
    13 public class DecoratorMain
    14 {
    15     public static void main(String[] args)
    16     {
    17         AbstractCoffeeComponent fatCatCoffeeOrder;
    18         fatCatCoffeeOrder = new Expresso();
    19         fatCatCoffeeOrder = new Milk(fatCatCoffeeOrder);
    20         System.out.println("order desc:" + fatCatCoffeeOrder.getDescription());
    21         System.out.println("order price:" + fatCatCoffeeOrder.cost());
    22 
    23 
    24         AbstractCoffeeComponent thinCatCoffeeOrder;
    25         thinCatCoffeeOrder = new Decaf();
    26         thinCatCoffeeOrder = new Whip(thinCatCoffeeOrder);
    27         thinCatCoffeeOrder = new Whip(thinCatCoffeeOrder);
    28         thinCatCoffeeOrder = new Tea(thinCatCoffeeOrder);
    29         System.out.println("order desc:" + thinCatCoffeeOrder.getDescription());
    30         System.out.println("order price:" + thinCatCoffeeOrder.cost());
    31 
    32     }
    33 }

    输出结果:

    1 order desc:Milk:5.0+Expresso:31.0
    2 order price:36.0
    3 order desc:Tea:10.0+Whip:3.0+Whip:3.0+Decaf:30.0
    4 order price:46.0
  • 相关阅读:
    7.$a = 'abcdef'; 请取出$a的值并打印出第一个字母
    8.PHP可以和sql server/oracle等数据库连接吗?
    6.能够使HTML和PHP分离开使用的模板
    4.用PHP打印出前一天的时间格式是2006-5-10 22:21:21
    5.echo(),print(),print_r()的区别
    3.数据库中的事务是什么?
    spring中配置quartz调用两次及项目日志log4j不能每天生成日志解决方法
    tomcat7性能调优与配置(以windows版为例)
    eclipse中maven下载不了私服上面的第三方包问题
    birt4.6部署到tomcat及启动服务报错解决方法
  • 原文地址:https://www.cnblogs.com/Artemisblog/p/6597624.html
Copyright © 2011-2022 走看看