码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式 学习 4:

时间:2016-04-26 22:12:34      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:


七个结构型模式之4(装饰模式,外观模式,享元模式,代理模式)


装饰模式:

 Sunny软件公司基于面向对象技术开发了一套图形界面构件库VisualComponent,该构件库提供了大量基本构件,如窗体、文本框、列表框等,由于在使用该构件库时,用户经常要求定制一些特效显示效果,如带滚动条的窗体、带黑色边框的文本框、既带滚动条又带黑色边框的列表框等等,因此经常需要对该构件库进行扩展以增强其功能

如何提高图形界面构件库性的可扩展性并降低其维护成本是Sunny公司开发人员必须面对的一个问题?


答案:


//抽象界面构件类:抽象构件类,为了突出与模式相关的核心代码,对原有控件代码进行了大量的简化

abstract class Component

{

       public  abstract void display();

}

 

//窗体类:具体构件类

class Window extends Component

{

       public  void display()

       {

              System.out.println("显示窗体!");

       }

}

 

//文本框类:具体构件类

class TextBox extends Component

{

       public  void display()

       {

              System.out.println("显示文本框!");

       }

}

 

//列表框类:具体构件类

class ListBox extends Component

{

       public  void display()

       {

              System.out.println("显示列表框!");

       }

}

 

//构件装饰类:抽象装饰类

class ComponentDecorator extends Component

{

       private Component component;  //维持对抽象构件类型对象的引用

 

       public ComponentDecorator(Component  component)  //注入抽象构件类型的对象

       {

              this.component = component;

       }

 

       public void display()

       {

              component.display();

       }

}

 

//滚动条装饰类:具体装饰类

class ScrollBarDecorator extends  ComponentDecorator

{

       public ScrollBarDecorator(Component  component)

       {

              super(component);

       }

 

       public void display()

       {

              this.setScrollBar();

              super.display();

       }

 

       public  void setScrollBar()

       {

              System.out.println("为构件增加滚动条!");

       }

}

 

//黑色边框装饰类:具体装饰类

class BlackBorderDecorator extends  ComponentDecorator

{

       public BlackBorderDecorator(Component  component)

       {

              super(component);

       }

 

       public void display()

       {

              this.setBlackBorder();

              super.display();

       }

 

       public  void setBlackBorder()

       {

              System.out.println("为构件增加黑色边框!");

       }

}

      编写如下客户端测试代码:

class Client

{

       public  static void main(String args[])

       {

              Component component,componentSB;  //使用抽象构件定义

              component = new Window(); //定义具体构件

              componentSB = new  ScrollBarDecorator(component); //定义装饰后的构件

              componentSB.display();

       }

}


技术分享


class SubSystemA

{

    public void MethodA()

    {

        //业务实现代码

    }

}


class SubSystemB

{

    public void MethodB()

    {

        //业务实现代码

     }

}


class SubSystemC

{

    public void MethodC()

    {

        //业务实现代码

    }

}


class Facade

{

    private SubSystemA obj1 = new SubSystemA();

    private SubSystemB obj2 = new SubSystemB();

    private SubSystemC obj3 = new SubSystemC();


    public void Method()

    {

        obj1.MethodA();

        obj2.MethodB();

        obj3.MethodC();

    }

}


class Program

{

    static void Main(string[] args)

    {

        Facade facade = new Facade();

        facade.Method();

    }

}


享元模式

Sunny软件公司欲开发一个围棋软件,Sunny软件公司开发人员通过对围棋软件进行分析,发现在围棋棋盘中包含大量的黑子和白子,它们的形状、大小都一模一样,只是出现的位置不同而已。如果将每一个棋子都作为一个独立的对象存储在内存中,将导致该围棋软件在运行时所需内存空间较大,如何降低运行代价、提高系统性能是Sunny公司开发人员需要解决的一个问题



IgoChessman充当抽象享元类,BlackIgoChessmanWhiteIgoChessman充当具体享元类,IgoChessmanFactory充当享元工厂类。完整代码如下所示:

[java] view plain copy


  1. import java.util.*;  
  2.   
  3. //围棋棋子类:抽象享元类  
  4. abstract class IgoChessman {  
  5.     public abstract String getColor();  
  6.   
  7.     public void display() {  
  8.         System.out.println("棋子颜色:" + this.getColor());    
  9.     }  
  10. }  
  11.   
  12. //黑色棋子类:具体享元类  
  13. class BlackIgoChessman extends IgoChessman {  
  14.     public String getColor() {  
  15.         return "黑色";  
  16.     }     
  17. }  
  18.   
  19. //白色棋子类:具体享元类  
  20. class WhiteIgoChessman extends IgoChessman {  
  21.     public String getColor() {  
  22.         return "白色";  
  23.     }  
  24. }  
  25.   
  26. //围棋棋子工厂类:享元工厂类,使用单例模式进行设计  
  27. class IgoChessmanFactory {  
  28.     private static IgoChessmanFactory instance = new IgoChessmanFactory();  
  29.     private static Hashtable ht; //使用Hashtable来存储享元对象,充当享元池  
  30.       
  31.     private IgoChessmanFactory() {  
  32.         ht = new Hashtable();  
  33.         IgoChessman black,white;  
  34.         black = new BlackIgoChessman();  
  35.         ht.put("b",black);  
  36.         white = new WhiteIgoChessman();  
  37.         ht.put("w",white);  
  38.     }  
  39.       
  40.     //返回享元工厂类的唯一实例  
  41.     public static IgoChessmanFactory getInstance() {  
  42.         return instance;  
  43.     }  
  44.       
  45.     //通过key来获取存储在Hashtable中的享元对象  
  46.     public static IgoChessman getIgoChessman(String color) {  
  47.         return (IgoChessman)ht.get(color);    
  48.     }  
  49. }  

      编写如下客户端测试代码:


  1. class Client {  
  2.     public static void main(String args[]) {  
  3.         IgoChessman black1,black2,black3,white1,white2;  
  4.         IgoChessmanFactory factory;  
  5.           
  6.         //获取享元工厂对象  
  7.         factory = IgoChessmanFactory.getInstance();  
  8.   
  9.         //通过享元工厂获取三颗黑子  
  10.         black1 = factory.getIgoChessman("b");  
  11.         black2 = factory.getIgoChessman("b");  
  12.         black3 = factory.getIgoChessman("b");  
  13.         System.out.println("判断两颗黑子是否相同:" + (black1==black2));  
  14.   
  15.         //通过享元工厂获取两颗白子  
  16.         white1 = factory.getIgoChessman("w");  
  17.         white2 = factory.getIgoChessman("w");  
  18.         System.out.println("判断两颗白子是否相同:" + (white1==white2));  
  19.   
  20.         //显示棋子  
  21.         black1.display();  
  22.         black2.display();  
  23.         black3.display();  
  24.         white1.display();  
  25.         white2.display();  
  26.     }  
  27. }  


代理模式

问题:

某软件公司承接了某信息咨询公司的收费商务信息查询系统的开发任务,该系统的基本需求如下:

       (1) 在进行商务信息查询之前用户需要通过身份验证,只有合法用户才能够使用该查询系统;

       (2) 在进行商务信息查询时系统需要记录查询日志,以便根据查询次数收取查询费用。

       该软件公司开发人员已完成了商务信息查询模块的开发任务,现希望能够以一种松耦合的方式向原有系统增加身份验证和日志记录功能,客户端代码可以无区别地对待原始的商务信息查询模块和增加新功能之后的商务信息查询模块,而且可能在将来还要在该信息查询模块中增加一些新的功能。

       试使用代理模式设计并实现该收费商务信息查询系统。

技术分享



代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层

  在实际开发过程中,代理类的实现比上述代码要复杂很多,代理模式根据其目的和实现方式不同可分为很多种类,其中常用的几种代理模式简要说明如下:

       (1) 远程代理(Remote Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又称为大使(Ambassador)

       (2) 虚拟代理(Virtual Proxy)如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。

       (3) 保护代理(Protect Proxy)控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。

       (4) 缓冲代理(Cache Proxy)为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。

       (5) 智能引用代理(Smart Reference Proxy)当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等

远程代理(Remote Proxy)是一种常用的代理模式,它使得客户端程序可以访问在远程主机上的对象,远程主机可能具有更好的计算性能与处理速度,可以快速响应并处理客户端的请求。远程代理可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户端完全可以认为被代理的远程业务对象是在本地而不是在远程,而远程代理对象承担了大部分的网络通信工作,并负责对远程业务方法的调用。

       远程代理示意图如图15-5所示,客户端对象不能直接访问远程主机中的业务对象,只能采取间接访问的方式。远程业务对象在本地主机中有一个代理对象,该代理对象负责对远程业务对象的访问和网络通信,它对于客户端对象而言是透明的。客户端无须关心实现具体业务的是谁,只需要按照服务接口所定义的方式直接与本地主机中的代理对象交互即可。


技术分享

虚拟代理(Virtual Proxy)也是一种常用的代理模式,对于一些占用系统资源较多或者加载时间较长的对象,可以给这些对象提供一个虚拟代理。在真实对象创建成功之前虚拟代理扮演真实对象的替身,而当真实对象创建之后,虚拟代理将用户的请求转发给真实对象。

       通常,在以下两种情况下可以考虑使用虚拟代理:

        (1) 由于对象本身的复杂性或者网络等原因导致一个对象需要较长的加载时间,此时可以用一个加载时间相对较短的代理对象来代表真实对象。通常在实现时可以结合多线程技术,一个线程用于显示代理对象,其他线程用于加载真实对象。这种虚拟代理模式可以应用在程序启动的时候,由于创建代理对象在时间和处理复杂度上要少于创建真实对象,因此,在程序启动时,可以用代理对象代替真实对象初始化,大大加速了系统的启动时间。当需要使用真实对象时,再通过代理对象来引用,而此时真实对象可能已经成功加载完毕,可以缩短用户的等待时间。

      (2) 当一个对象的加载十分耗费系统资源的时候,也非常适合使用虚拟代理。虚拟代理可以让那些占用大量内存或处理起来非常复杂的对象推迟到使用它们的时候才创建,而在此之前用一个相对来说占用资源较少的代理对象来代表真实对象,再通过代理对象来引用真实对象。为了节省内存,在第一次引用真实对象时再创建对象,并且该对象可被多次重用,在以后每次访问时需要检测所需对象是否已经被创建,因此在访问该对象时需要进行存在性检测,这需要消耗一定的系统时间,但是可以节省内存空间,这是一种用时间换取空间的做法。

       无论是以上哪种情况,虚拟代理都是用一个“虚假”的代理对象来代表真实对象,通过代理对象来间接引用真实对象,可以在一定程度上提高系统的性能。







设计模式 学习 4:

标签:

原文地址:http://blog.csdn.net/xiaoliuliu2050/article/details/51226099

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!