zoukankan      html  css  js  c++  java
  • 设计模式——代理模式与装饰模式的异同

    两种模式的特点


    装饰模式:

      在不改变接口的前提下,动态扩展对象的访问。
      动态继承,让类具有在运行期改变行为的能力。
      装饰模式,突出的是运行期增加行为,这和继承是不同的,继承是在编译期增加行为
      强调:增强

    代理模式:

      在不改变接口的前提下,控制对象的访问。
      1.从封装的角度讲,是为了解决类与类之间相互调用而由此导致的耦合关系,可以说是接口的另外一个层引用。
        比如:在a类->b代理->c类这个关系中,c类的一切行为都隐藏在b中。即调用者不知道要访问的内容与代理了什么对象。
      2.从复用的角度讲,可以解决不同类调用一个复杂类时,仅仅因较小的改变而导致整个复杂类新建一个类。
        比如:a类->c类1;b类->c类2。
        可以变为a类->ca代理类->c类;b类->cb代理类-c类。
      代理模式,是类之间的封装和(某方面的)复用。
      强调:限制

    举个例子说明问题


      下面通过一个例子来说明两者的不同。当我们冲咖啡的时候,首先你要拿咖啡粉冲好一杯咖啡,然后你可以考虑是否加方

      那么咖啡这个东西就可以通过糖或奶或者糖和奶,变成加糖的咖啡、加奶的咖啡、加糖加奶的咖啡。

      但是它还是一杯咖啡,只是它的属性进行了扩展。

      接下来分别通过装饰模式与代理模式,模拟这个过程。

    1.装饰模式

      测试代码:

     1 Cafe cafe = new ConcreteCafe();
     2  
     3 Cafe milkCafe = new MilkDecorator(cafe);
     4 milkCafe.getCafe();
     5 System.out.println("----------------------------------------");
     6 Cafe sugarCafe = new SugarDecorator(cafe);
     7 sugarCafe.getCafe();
     8 System.out.println("----------------------------------------");
     9 Cafe sugarMilkCafe = new MilkDecorator(new SugarDecorator(new ConcreteCafe()));
    10 sugarMilkCafe.getCafe();
    11 System.out.println("----------------------------------------");
    12 Cafe milkSugarCafe = new SugarDecorator(new MilkDecorator(cafe));
    13 milkSugarCafe.getCafe();
    14 System.out.println("----------------------------------------");

      就像使用IO流一样:

    1 BufferedReader in1 = new BufferedReader(new InputStreamReader(new FileInputStream(file)));//字符流
    2 DataInputStream in2 = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));//字节流
      // DataInputStream-从数据流读取字节,并将它们装换为正确的基本类型值或字符串
      // BufferedInputStream-可以通过减少读写次数来提高输入和输出的速度

      对类进行了功能的增强。

    2.代理模式

      测试代码:

    1 Cafe cafe = new Proxy();
    2 cafe.getCafe();

    现在可以很清楚的看到:

      1. 装饰模式可以让使用者直观的看到增强了哪些功能,而代理模式完全限制了使用者。

      2. 对装饰模式来说,装饰者(Decorator)和被装饰者(Cafe)都实现同一个 接口。

      3. 对代理模式来说,代理类(Proxy Class)和真实处理的类(Real Class)都实现同一个接口。

      4. 此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。

    装饰模式与继承的比较


      明显的,装饰模式可以动态的扩展对象的行为。

      比如某对象有30项行为,但是在第一阶段用到1-20行为,第二阶段用到11-30项行为,所以这时候,就可以只定义11-20的行为。

      在第一阶段运行时,可以将1-10的行为以“装饰1”给加上

      到第二阶段运行时,可以将“装饰1”去掉,将21-30的能以“装饰2”给加上。

      但是继承是在编译期增加行为。

    装饰模式的优缺点


    优点:

      1. 装饰模式可以提供比继承更多地灵活性。
      2. 可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
      3. 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
      4. 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。

    缺点:

      1. 会产生很多的小对象(具体装饰类),增加了系统的复杂性。
      2. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

    参考博文:

    UML类图

    修饰模式与代理模式的区别

    设计模式之——装饰模式与代理模式的区别

    Java之美——设计模式

    装饰者模式

    源码:

    装饰者模式:

     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:10:23
     5  */
     6 package cafe;
     7 
     8 /**
     9  * @author zhengbinMac
    10  * 抽象构件角色
    11  */
    12 public interface Cafe {
    13     
    14     public void getCafe();
    15     
    16 }
    Cafe.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:11:03
     5  */
     6 package cafe;
     7 
     8 /**
     9  * @author zhengbinMac
    10  * 具体构件角色
    11  */
    12 public class ConcreteCafe implements Cafe{
    13 
    14     @Override
    15     public void getCafe() {
    16         System.out.println("上一杯原味咖啡!");
    17     }
    18     
    19 }
    ConcreteCafe.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:13:41
     5  */
     6 package cafe;
     7 
     8 /**
     9  * @author zhengbinMac
    10  * 装饰角色
    11  */
    12 public class Decorator implements Cafe{
    13 
    14     public Cafe cafe;
    15     
    16     public Decorator(Cafe cafe) {
    17         this.cafe = cafe;
    18     }
    19 
    20     @Override
    21     public void getCafe() {
    22         cafe.getCafe();
    23     }
    24     
    25 }
    Decorator.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:13:29
     5  */
     6 package cafe;
     7 
     8 /**
     9  * @author zhengbinMac
    10  * 具体装饰角色
    11  */
    12 public class MilkDecorator extends Decorator{
    13 
    14     public MilkDecorator(Cafe cafe) {
    15         super(cafe);
    16     }
    17     
    18     @Override
    19     public void getCafe() {
    20         super.getCafe();
    21         this.addMilk();
    22     }
    23     
    24     private void addMilk() {
    25         System.out.println("加奶!");
    26     }
    27     
    28 }
    MilkDecorator.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:14:22
     5  */
     6 package cafe;
     7 
     8 /**
     9  * @author zhengbinMac
    10  * 具体装饰角色
    11  */
    12 public class SugarDecorator extends Decorator{
    13 
    14     public SugarDecorator(Cafe cafe) {
    15         super(cafe);
    16     }
    17     
    18     @Override
    19     public void getCafe() {
    20         super.getCafe();
    21         this.addSugar();
    22     }
    23     
    24     private void addSugar() {
    25         System.out.println("加糖!");
    26     }
    27     
    28 }
    SugarDecorator.java
      1 /**
      2  * Copyright 2016 Zhengbin's Studio.
      3  * All right reserved.
      4  * 2016年6月23日 上午11:18:32
      5  */
      6 package cafe;
      7 
      8 import java.io.BufferedInputStream;
      9 import java.io.BufferedReader;
     10 import java.io.DataInputStream;
     11 import java.io.File;
     12 import java.io.FileInputStream;
     13 import java.io.IOException;
     14 import java.io.InputStream;
     15 import java.io.InputStreamReader;
     16 import java.util.Date;
     17 
     18 /**
     19  * @author zhengbinMac
     20  * 测试类
     21  */
     22 public class Test {
     23 
     24     public static void main(String[] args) throws IOException {
     25         Cafe cafe = new ConcreteCafe();
     26         
     27         Cafe milkCafe = new MilkDecorator(cafe);
     28         milkCafe.getCafe();
     29         System.out.println("----------------------------------------");
     30         Cafe sugarCafe = new SugarDecorator(cafe);
     31         sugarCafe.getCafe();
     32         System.out.println("----------------------------------------");
     33         Cafe sugarMilkCafe = new MilkDecorator(new SugarDecorator(new ConcreteCafe()));
     34         sugarMilkCafe.getCafe();
     35         System.out.println("----------------------------------------");
     36         Cafe milkSugarCafe = new SugarDecorator(new MilkDecorator(cafe));
     37         milkSugarCafe.getCafe();
     38         System.out.println("----------------------------------------");
     39         
     40         File file = new File("/Users/zhengbinMac/test.txt");
     41         
     42         FileInputStream in2 = new FileInputStream(file);
     43         byte[] tempByte = new byte[1024];
     44         int hasRead = 0;
     45         System.out.println("开始时间:" + new Date().getTime());
     46         while((hasRead = in2.read(tempByte)) > 0) {
     47             System.out.println(new String(tempByte,0,hasRead));
     48         }
     49         System.out.println("结束时间:" + new Date().getTime());
     50         in2.close();
     51         
     52         System.out.println("----------------------------------------");
     53         
     54         FileInputStream in4 = new FileInputStream(file);
     55         byte[] tempByte2 = new byte[(int)file.length()];
     56         System.out.println("开始时间:" + new Date().getTime());
     57         in4.read(tempByte2);
     58         System.out.println("结束时间:" + new Date().getTime());
     59         in4.close();
     60         System.out.println(new String(tempByte2));
     61         
     62         System.out.println("----------------------------------------");
     63         
     64 //        DataInputStream in3 = new DataInputStream(new FileInputStream(file));
     65 //        String s;
     66 //        System.out.println("开始时间:" + new Date().getTime());
     67 //        while((s=in3.readLine()) != null) {
     68 //            System.out.println(s);
     69 //        }
     70 //        System.out.println("结束时间:" + new Date().getTime());
     71 //        in3.close();
     72         
     73         System.out.println("----------------------------------------");
     74         
     75 //        DataInputStream in5 = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
     76 //        String s1;
     77 //        System.out.println("开始时间:" + new Date().getTime());
     78 //        while((s1 = in5.readLine()) != null) {
     79 //            System.out.println(s1);
     80 //        }
     81 //        System.out.println("结束时间:" + new Date().getTime());
     82 //        in5.close();
     83         
     84         System.out.println("----------------------------------------");
     85         
     86         BufferedReader in6 = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
     87         String s2;
     88         System.out.println("开始时间:" + new Date().getTime());
     89         while((s2 = in6.readLine()) != null) {
     90             System.out.println(s2);
     91         }
     92         System.out.println("结束时间:" + new Date().getTime());
     93         in6.close();
     94         
     95         System.out.println("----------------------------------------");
     96         
     97         
     98     }
     99     
    100 }
    Test.java

    代理模式:

     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月26日 下午8:30:42
     5  */
     6 package cafe3;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public interface Cafe {
    13     
    14     public void getCafe();
    15     
    16 }
    Cafe.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月26日 下午8:32:08
     5  */
     6 package cafe3;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public class ConcreteCafe implements Cafe{
    13 
    14     @Override
    15     public void getCafe() {
    16         System.out.println("上一杯原味咖啡!");
    17     }
    18     
    19 }
    ConcreteCafe.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月26日 下午8:33:05
     5  */
     6 package cafe3;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public class Proxy implements Cafe{
    13 
    14     private ConcreteCafe concreteCafe;
    15     
    16     public Proxy() {
    17         this.concreteCafe = new ConcreteCafe();
    18     }
    19     
    20     @Override
    21     public void getCafe() {
    22         concreteCafe.getCafe();
    23         addMilk();
    24         addSugar();
    25     }
    26     
    27     private void addMilk() {
    28         System.out.println("加奶!");
    29     }
    30     
    31     private void addSugar() {
    32         System.out.println("加糖!");
    33     }
    34 
    35 }
    Proxy.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月26日 下午8:38:51
     5  */
     6 package cafe3;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public class Test {
    13 
    14     public static void main(String[] args) {
    15         Cafe cafe = new Proxy();
    16         cafe.getCafe();
    17     }
    18     
    19 }
    Test.java

    继承:

     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:30:41
     5  */
     6 package cafe2;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public class Cafe {
    13     
    14     public void getCafe() {
    15         System.out.println("来一杯原味咖啡!");
    16     }
    17     
    18 }
    Cafe.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:32:32
     5  */
     6 package cafe2;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public class MilkCafe extends Cafe{
    13 
    14     @Override
    15     public void getCafe() {
    16         super.getCafe();
    17         this.addMilk();
    18     }
    19     
    20     private void addMilk() {
    21         System.out.println("加奶!");
    22     }
    23 }
    MilkCafe.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:31:09
     5  */
     6 package cafe2;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public class SugarCafe extends Cafe{
    13     
    14     @Override
    15     public void getCafe() {
    16         super.getCafe();
    17         this.addSugar();
    18     }
    19     
    20     private void addSugar() {
    21         System.out.println("加糖!");
    22     }
    23 }
    SugarCafe.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月26日 下午3:01:26
     5  */
     6 package cafe2;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public class SugarMilkCafe extends Cafe{
    13     @Override
    14     public void getCafe() {
    15         super.getCafe();
    16         this.addSugarAndMilk();
    17     }
    18     
    19     private void addSugarAndMilk() {
    20         System.out.println("加糖!");
    21         System.out.println("加奶!");
    22     }
    23 }
    SugarMilkCafe.java
     1 /**
     2  * Copyright 2016 Zhengbin's Studio.
     3  * All right reserved.
     4  * 2016年6月23日 上午11:33:22
     5  */
     6 package cafe2;
     7 
     8 /**
     9  * @author zhengbinMac
    10  *
    11  */
    12 public class Test {
    13 
    14     public static void main(String[] args) {
    15         Cafe milkCafe = new MilkCafe();
    16         milkCafe.getCafe();
    17         
    18         Cafe sugarCafe = new SugarCafe();
    19         sugarCafe.getCafe();
    20         
    21         Cafe sugarMilkCafe = new SugarMilkCafe();
    22         sugarMilkCafe.getCafe();
    23     }
    24     
    25 }
    Test.java
  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/zhengbin/p/5618564.html
Copyright © 2011-2022 走看看