• 23种设计模式之四(装饰者模式)


    装饰者模式:(动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性)

     其别名为包装器(Wrapper);装饰模式是一种对象结构模式。

    设计原则:对扩展开放、对修改关闭,这句话体现在我如果想扩展被装饰者类的行为,无须修改装饰者抽象类;只需继承装饰者抽象类,实现额外的一些装饰或者叫行为即可对被装饰者进行包装。

    所以:扩展体现在继承、修改体现在子类中,而不是具体的抽象类,这充分体现了依赖倒置原则。

    举例:

    咖啡馆订单项目:
    1)、咖啡种类:Espresso、ShortBlack、LongBlack、Decaf
    2)、调料:Milk、Soy、Chocolate
    3)、扩展性好、改动方便、维护方便

    就如同调制一杯饮品:

      主体:黑咖啡、浓缩黑咖啡、无咖啡因咖啡、意式浓缩咖啡

      包装:牛奶、巧克力、豆浆

     超类(被装饰者):

     1 package com.java.jikexueyuan.coffeebar;
     2 
     3 public abstract class Drink {
     4     public String description="";
     5     private float price=0f;;
     6     
     7     
     8     public void setDescription(String description)
     9     {
    10         this.description=description;
    11     }
    12     
    13     public String getDescription()
    14     {
    15         return description+"-"+this.getPrice();
    16     }
    17     public float getPrice()
    18     {
    19         return price;
    20     }
    21     public void setPrice(float price)
    22     {
    23         this.price=price;
    24     }
    25     public abstract float cost();
    26     
    27 }
    Drink

     主体(被装饰者):

     1 package com.java.jikexueyuan.coffeebar.coffee;
     2 
     3 import com.java.jikexueyuan.coffeebar.Drink;
     4 
     5 //中间层:将各种咖啡共有的功能进行封装
     6 public  class Coffee extends Drink {
     7     @Override
     8     public float cost() {
     9         // TODO Auto-generated method stub
    10         return super.getPrice();
    11     }
    12 }
    Coffee
     1 package com.java.jikexueyuan.coffeebar.coffee;
     2 
     3 public class ShortBlack extends Coffee{
     4     
     5     public ShortBlack(){
     6         super.setDescription("ShortBlack");
     7         super.setPrice(5.0f);
     8     }
     9 
    10 }
    ShortBlack
     1 package com.java.jikexueyuan.coffeebar.coffee;
     2 
     3 public class LongBlack extends Coffee{
     4     
     5     public LongBlack(){
     6         super.setDescription("LongBlack");
     7         super.setPrice(6.0f);
     8     }
     9 
    10 }
    LongBlack
    1 package com.java.jikexueyuan.coffeebar.coffee;
    2 
    3 public class Decaf extends Coffee {
    4     public Decaf()    {
    5         super.setDescription("Decaf");
    6         super.setPrice(3.0f);
    7     }
    8 }
    Decaf
     1 package com.java.jikexueyuan.coffeebar.coffee;
     2 
     3 public class Espresso extends Coffee{
     4     
     5     public Espresso(){
     6         super.setDescription("Espresso");
     7         super.setPrice(4.0f);
     8     }
     9 
    10 }
    Espresso

    装饰者:

     1 package com.java.jikexueyuan.coffeebar.decorator;
     2 
     3 import com.java.jikexueyuan.coffeebar.Drink;
     4 
     5 //中间层:将各种调料的共有功能封装出来
     6 public  class Decorator extends Drink {
     7     private Drink Obj;
     8 
     9     public Decorator(Drink Obj){
    10         this.Obj=Obj;
    11     };
    12     
    13     
    14     @Override
    15     public float cost() {
    16         return super.getPrice()+Obj.cost();
    17     }
    18 
    19     @Override
    20     public String getDescription(){
    21         return super.description+"-"+super.getPrice()+"&&"+Obj.getDescription();
    22     }
    23     
    24     }
    Decorator
    包装(装饰):
     1 package com.java.jikexueyuan.coffeebar.decorator;
     2 
     3 import com.java.jikexueyuan.coffeebar.Drink;
     4 
     5 public class Chocolate extends Decorator {
     6 
     7     public Chocolate(Drink Obj) {        
     8         super(Obj);
     9         // TODO Auto-generated constructor stub
    10         super.setDescription("Chocolate");
    11         super.setPrice(3.0f);
    12     }
    13 
    14 }
    Chocolate
     1 package com.java.jikexueyuan.coffeebar.decorator;
     2 
     3 import com.java.jikexueyuan.coffeebar.Drink;
     4 
     5 public class Milk extends Decorator {
     6 
     7     public Milk(Drink Obj) {        
     8         super(Obj);
     9         // TODO Auto-generated constructor stub
    10         super.setDescription("Milk");
    11         super.setPrice(2.0f);
    12     }
    13 
    14 }
    Milk
     1 package com.java.jikexueyuan.coffeebar.decorator;
     2 
     3 import com.java.jikexueyuan.coffeebar.Drink;
     4 
     5 public class Soy extends Decorator {
     6 
     7     public Soy(Drink Obj) {        
     8         super(Obj);
     9         // TODO Auto-generated constructor stub
    10         super.setDescription("Soy");
    11         super.setPrice(1.5f);
    12     }
    13 
    14 }
    Soy

    测试:

     1 package com.java.jikexueyuan.coffeebar;
     2 
     3 import com.java.jikexueyuan.coffeebar.coffee.Decaf;
     4 import com.java.jikexueyuan.coffeebar.coffee.LongBlack;
     5 import com.java.jikexueyuan.coffeebar.decorator.Chocolate;
     6 import com.java.jikexueyuan.coffeebar.decorator.Milk;
     7 
     8 public class CoffeeBar {
     9 
    10 
    11     public static void main(String[] args) {
    12         
    13         Drink order;
    14         order=new Decaf();
    15         System.out.println("order1 price:"+order.cost());
    16         System.out.println("order1 desc:"+order.getDescription());
    17         
    18         System.out.println("****************");
    19         order=new LongBlack();
    20         order=new Milk(order);
    21         order=new Chocolate(order);
    22         order=new Chocolate(order);
    23         System.out.println("order2 price:"+order.cost());
    24         System.out.println("order2 desc:"+order.getDescription());
    25         
    26     }
    27 
    28 
    29 }
    main
    order1 price:3.0
    order1 desc:Decaf-3.0
    ****************
    order2 price:14.0
    order2 desc:Chocolate-3.0&&Chocolate-3.0&&Milk-2.0&&LongBlack-6.0
    运行结果:

    Java内置装饰者:

    2、编写自己的Java I/O装饰者:

     1 package com.java.jikexueyuan.myiodecorator;
     2 
     3 import java.io.FilterInputStream;
     4 import java.io.IOException;
     5 import java.io.InputStream;
     6 
     7 public class UpperCaseInputStream extends FilterInputStream{
     8 
     9     protected UpperCaseInputStream(InputStream in) {
    10         super(in);
    11         // TODO Auto-generated constructor stub
    12     }
    13 
    14     public int read() throws IOException
    15     {
    16         int c=super.read();
    17         return c==-1?c:Character.toUpperCase((char)(c));
    18     }
    19     public int read(byte[] b,int offset,int len) throws IOException
    20     {
    21         int result=super.read(b,offset,len);
    22         for(int i=0;i<result;i++)
    23         {
    24             b[i]=(byte)Character.toUpperCase((char)(b[i]));
    25         }
    26         
    27         return result;
    28     }
    29 }
    UpperCaseInputStream
     1 package com.java.jikexueyuan.myiodecorator;
     2 
     3 import java.io.BufferedInputStream;
     4 import java.io.FileInputStream;
     5 import java.io.FileNotFoundException;
     6 import java.io.IOException;
     7 import java.io.InputStream;
     8 
     9 public class InputTest {
    10     public static void main(String[] args) {
    11         int c;
    12         try {
    13             InputStream in = new UpperCaseInputStream(new BufferedInputStream(
    14                     new FileInputStream("D:\test\test.txt")));
    15             while((c=in.read())>=0)
    16             {
    17                 System.out.print((char)c);
    18                 
    19             }
    20         } catch (IOException e) {
    21             // TODO Auto-generated catch block
    22             e.printStackTrace();
    23         }
    24 
    25     }
    26 }
    main:
    ZHE SHI CE SHI WEN JIAN !
    运行结果:

    注意:
    一个装饰者类的接口必须与被装饰者的接口一致;
    尽量保持具体装饰者类作为一个“轻”类,也就是说不要把太多的逻辑和状态放到具体装饰者类去实现;
    优先使用组合、聚合原则,少用继承。

    (参考:http://www.cnblogs.com/chenxing818/p/4705919.html或http://blog.csdn.net/jason0539/article/details/22713711)

    优点:
    装饰模式与类继承的目的都是扩展对象的功能,但是装饰模式可以提供比类继承更多的灵活性;
    通过使用不同的具体装饰类以及这些装饰类的排列组合,开发者可以创造出很多不同行为的组合;
    缺点:
    这种比类继承更加灵活机动的特性,也同时意味着装饰模式比类继承更容易出错;
    使用装饰模式增加了代码的复杂度。

    应用场景:

    1、在不影响其它对象情况下,以动态透明的方式给单个对象添加职责;

    2、需要动态给一个对象添加功能,这些功能可以在动态的被撤销;

    3、当不能采用类继承的方式进行扩展时。

      一种情况是可能有大量独立的扩展,每一种组合将产生大量的子类,使得子类数量呈爆炸性增长;

      另一种情况可以是因为类定义不能继承(final)或不能用于生成子类。

  • 相关阅读:
    swoole推送信息一对一,一对多
    laravel5.8笔记十:Redis操作
    laravel5.8笔记九:数据库曾、更、查、删
    laravel5.8笔记八:数据库(单库和多库)
    laravel5.8笔记七:语言包
    laravel5.8笔记六:公共函数和常量设置
    laravel5.8笔记五:基类控制器和基类模型
    laravel5.8笔记四:中间件
    laravel5.8笔记四:路由
    微软开源自动机器学习工具NNI安装与使用
  • 原文地址:https://www.cnblogs.com/mmzs/p/7674260.html
Copyright © 2020-2023  润新知