所访问的真人真事对象与代理对象急需落成平等的接口,所走访的真实对象与代理对象急需已毕平等的接口

【学习难度:★★★☆☆,使用效能:★★★★☆】

【学习难度:★★★☆☆,使用功用:★★★★☆】
一向出处:http://woquanke.com/books/gof/
梳理和学习:https://github.com/BruceOuyang/boy-design-pattern
简书日期: 2018/03/15
简书首页:https://www.jianshu.com/p/0fb891a7c5ed

定义

  代理方式:给某二个目的提供三个代理或占位符,并由代理对象来决定对原对象的造访。

代办格局是常用的结构型设计方式之一,当不能直接访问有些对象或访问有个别对象存在困难时得以通过二个代理对象来直接访问,为了保障客户端选用的透明性,所访问的实在对象与代理对象急需贯彻平等的接口。根据代理形式的运用目的差异,代理形式又有啥不可分成四连串型,例如敬重代理、远程代理、虚拟代理、缓冲代理等,它们应用于不一致的场合,满足用户的不一致需要。

设计情势之代理形式(一)

代办形式是常用的结构型设计方式之一,当不能间接访问某些对象或访问某些对象存在困难时方可经过1个代理对象来直接访问,为了有限扶助客户端应用的透明性,所走访的真人真事对象与代理对象要求完毕平等的接口。根据代理方式的应用目的不同,代理方式又足以分为多样类型,例如爱慕代理、远程代理、虚拟代理、缓冲代理等,它们应用于不一致的场合,满意用户的两样须要。

15.1 代理格局概述

新近,代购已渐渐成为电子商务的三个要害分支。何谓代购,简而言之就是找人援救购销所须求的货色,当然你可能须求向实施代购的人付出必定的开销。代购平常分为三种档次:一种是因为在该地买不到某件商品,又大概是因为地点那件商品的价位比另内地段的贵,因而托人在任哪个地点方如故外国购置该商品,然后通过快递发货只怕直接带入回来;还有一种代购,由于消费者对想要购买的商品有关音信的干涸,自已力不从心鲜明其实际价值而又不想被商行宰,只可以委托中介机构帮其讲价或为其代买。代购网站为此应运而生,它为买主提供在线的代购服务,假使看中某海外购物网站上的货品,可以登录代购网站填写代购单并给付,代购网站会支持拓展买卖然后经过快递集团将货品发送给消费者。商品代购进度如图15-1所示:

澳门威尼斯人网址 1

图15-1 商品代购示意图

在软件开发中,也有一种设计情势可以提供与代购网站类似的意义。由于一些原因,客户端不想或不只怕一贯访问一个目的,此时可以通过多个叫作“代理”的观察众来落实直接访问,该方案对应的设计情势被称作代理形式。

代理情势是一种接纳很广泛的结构型设计情势,而且转移方式十三分多,常见的代理形式包含中长途代理、爱慕代理、虚拟代理、缓冲代理、智能引用代理等,后边将学习这么些不一样的代办格局。

代理情势定义如下:

代理情势:给某三个对象提供一个代理或占位符,并由代理对象来支配对原对象的拜会。
Proxy Pattern: Provide a surrogate or placeholder for another object to
control access to it.

代理形式是一种对象结构型格局。在代理格局中引入了3个新的代理对象,代理对象在客户端对象和对象对象时期起到中介的意义,它去掉客户不或许来看的情节和服务大概扩展客户须要的附加的新服务。

15.2 代理情势结构与落到实处

15.2.1 形式结构

代理格局的布局相比简单,其主干是代理类,为了让客户端可以一致性地对待真实对象和代办对象,在代理格局中引入了抽象层,代理格局社团如图15-2所示:

澳门威尼斯人网址 2

图15-2 代理方式结构图

由图15-2力所能及,代理形式涵盖如下多个角色:

(1)
Subject(抽象核心角色):它表明了实事求是焦点和代办大旨的联手接口,这样一来在其他利用真实主题的地点都得以应用代理核心,客户端平时须要针对抽象大旨角色举办编程。

(2)
Proxy(代理大旨角色):它涵盖了对真实宗旨的引用,从而可以在其余时候操作实际大旨对象;在代理大旨角色中提供二个与忠实大旨角色一样的接口,以便在别的时候都得以代替真实核心;代理大旨角色还足以操纵对真实核心的利用,负责在要求的时候创立和删除真实宗旨对象,并对实在核心对象的施用加以约束。经常,在代理核心剧中人物中,客户端在调用所引用的真人真事宗旨操作之前或之后还亟需履行其余操作,而不仅是仅仅调用真实核心对象中的操作。

(3)
RealSubject(真实宗旨角色):它定义了代理角色所表示的真实性对象,在实际大旨剧中人物中达成了诚实的事情操作,客户端可以透过代办大旨剧中人物直接调用真实大旨角色中定义的操作。

15.2.2 情势完结

代理方式的协会图比较简单,可是在真正的利用和兑现进程中要复杂很多,特别是代理类的安顿和贯彻。

空洞焦点类阐明了诚实大旨类和代理类的集体艺术,它可以是接口、抽象类或具体类,客户端针对抽象大旨类编程,一致性地对待真实主旨和代办大旨,典型的悬空宗旨类代码如下:

public abstract class Subject  
{  
    public abstract void request();  
}

实在大旨类继承了用空想来欺骗别人宗旨类,提供了工作方法的现实性贯彻,其至高无上代码如下:

public class RealSubject extends Subject  
{  
    @Override
    public void request()  
    {  
        //业务方法具体实现代码  
    }  
}

代理类也是纸上谈蚩尤旨类的子类,它维持一个对实在宗旨对象的引用,调用在实际主旨中落到实处的工作方法,在调用时可以在原始工作方法的根底上附加一些新的点子来对效能举办扩张或约束,最简便的代理类完毕代码如下:

class Proxy extends Subject  
{  
    /**
     * 维持一个对真实主题对象的引用 
     */
    private RealSubject realSubject = new RealSubject();   

    public void preRequest()   
    {
        //...  
    }  

    @Override
    public void request()   
    {  
        preRequest();  

        // 调用真实主题对象的方法 
        realSubject.request();  

        postRequest();  
    }  

    public void PostRequest()   
    {  
        // …  
    }  
}

在实际上付出进度中,代理类的落到实处比上述代码要复杂很多,代理形式根据其目的和促成方式各异可分为很多项目,其中常用的两种代理格局不难表达如下:

(1) 远程代理(Remote
Proxy):为1个放在差其余地址空间的目的提供1个地点的代办对象,那些差其他地点空间可以是在同等台主机中,也不过在另一台主机中,远程代理又称为大使(Ambassador)。

(2) 虚拟代理(Virtual
Proxy):倘若须求成立多少个财富消耗较大的靶子,先创制多少个消耗相对较小的目的来代表,真实对象只在急需时才会被真正创建。

(3) 爱护代理(Protect
Proxy):控制对贰个目标的拜访,可以给不一致的用户提供不一致级其余应用权限。

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

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

在这个常用的代办形式中,有个别代理类的规划极度复杂,例如远程代理类,它包裹了尾部互连网通信和对长途对象的调用,其促成比较复杂。

结构图

澳门威尼斯人网址 3

要素:
(1)
Subject(抽象主题角色):它表明了实在大旨和代理主旨的共同接口,那样一来在其他利用真实核心的地点都得以行使代理核心,客户端平常要求针对抽象大旨角色进行编程。
(2)
Proxy(代理主旨角色):它含有了对实在核心的引用,从而可以在别的时候操作实际核心对象;在代理主旨剧中人物中提供3个与真实大旨角色一样的接口,以便在别的时候都得以代替真实宗旨;代理宗旨角色还足以操纵对实在宗旨的行使,负责在须要的时候创制和删除真实核心对象,并对真实宗旨对象的使用加以约束。平时,在代理主旨角色中,客户端在调用所引用的真正核心操作从前或之后还亟需实践其它操作,而不仅是唯有调用真实主旨对象中的操作。
(3)
RealSubject(真实核心剧中人物):它定义了代办角色所表示的真正对象,在实际宗旨角色中落成了真格的的事务操作,客户端可以透过代理宗旨角色直接调用真实大旨剧中人物中定义的操作。

abstract class Subject  
{  
    public abstract void Request();  
}  

class RealSubject : Subject  
{  
    public override void Request()  
    {  
        //业务方法具体实现代码  
    }  
}  

class Proxy : Subject  
{  
    private RealSubject realSubject = new RealSubject(); //维持一个对真实主题对象的引用  

    public void PreRequest()   
    {  
        …...  
    }  

    public override void Request()   
    {  
        PreRequest();  
        realSubject.Request(); //调用真实主题对象的方法  
         PostRequest();  
    }  

    public void PostRequest()   
    {  
        ……  
    }  
}  

 

设计格局之代理情势(二)

15.3 代理方式拔取实例

上面通过几个选取实例来更是深造和精通代理格局。

15.3.1 实例证实

某软件商店承接了某消息咨询公司的收款商务音信查询系统的付出职务,该系列的基本须要如下:

(1)
在拓展商务新闻查询从前用户须求经过身份验证,唯有合法用户才能够使用该查询系统;

(2)
在拓展商务消息查询时系统须求记录查询日志,以便依照查询次数收取查询开销。

该软件集团开发人士已形成了商务音信查询模块的支出职分,现希望可以以一种松耦合的主意向原有系统增添身份验证和日志记录功用,客户端代码可以无不一样地对待原始的商务新闻查询模块和充实新职能之后的商务消息查询模块,而且只怕在今后还要在该音讯查询模块中加进部分新的作用。

试使用代理形式设计并促成该收费商务音信查询系统。

15.3.2 实例分析及类图

经过分析,能够利用一种间接访问的法子来贯彻该商务新闻查询系统的筹划,在客户端对象和音信查询对象之间增添三个代理对象,让代理对象来实出现份验证和日志记录等功能,而无须直接对原来的商务新闻查询对象举行修改,如图15-3所示:

澳门威尼斯人网址 4

图15-3 商务音信查询系统设计方案示意图

在图15-3中,客户端对象通过代理对象直接访问具有商务音信查询功用的实际对象,在代理对象中除去调用真实对象的商务音讯查询功用外,还增加了身份验证和日志记录等职能。使用代理形式设计该商务新闻查询系统,结构图如图15-4所示。

澳门威尼斯人网址 5

图15-4 商务新闻查询系统结构图

在图15-4中,业务类AccessValidator用于声明用户地方,业务类Logger用于记录用户查询日志,Searcher充当抽象宗旨脚色,RealSearcher充当真实宗旨角色,ProxySearcher充当代理核心剧中人物。

15.3.3 实例代码

(1)
AccessValidator:身份验证类,业务类,它提供格局Validate()来落到实处身份验证。

class AccessValidator  
{  
    //模拟实现登录验证  
    public boolean validate(string userId)   
    {  
        System.out.println("在数据库中验证用户'" + userId + "'是否是合法用户?");  
        if (userId.equals("杨过")) {  
            System.out.println("'{0}'登录成功!",userId);  
            return true;  
        }  
        else {  
            System.out.println("'{0}'登录失败!", userId);  
            return false;  
        }  
    }  
}  

(2) Logger:日志记录类,业务类,它提供形式Log()来保存日志。

class Logger  
{  
    //模拟实现日志记录  
    public void log(string userId) {  
        System.out.println("更新数据库,用户'{0}'查询次数+1!",userId);  
    }  
} 

(3) Searcher:抽象查询类,充当抽象核心角色,它申明了DoSearch()方法。

interface Searcher  
{  
    String doSearch(string userId, string keyword);  
}  

(4)
RealSearcher:具体查询类,充当真实核心剧中人物,它完结查询功用,提供方式DoSearch()来询问音讯。

class RealSearcher implements Searcher  
{  
    //模拟查询商务信息  
    public string doSearch(string userId, string keyword) {  
        System.out.println("用户'{0}'使用关键词'{1}'查询商务信息!",userId,keyword);  
        return "返回具体内容";  
    }  
}

(5)
ProxySearcher:代理查询类,充当代理大旨角色,它是询问代理,维持了对RealSearcher对象、AccessValidator对象和Logger对象的引用。

class ProxySearcher implements Searcher  
{  
    /**
     * 维持一个对真实主题的引用
     */
    private RealSearcher searcher = new RealSearcher();   
    private AccessValidator validator;  
    private Logger logger;  

    public string doSearch(string userId, string keyword)  
    {  
        //如果身份验证成功,则执行查询  
        if (this.validate(userId))  
        {  
            string result = searcher.doSearch(userId, keyword); //调用真实主题对象的查询方法  
            this.Log(userId); //记录查询日志  
            return result; //返回查询结果  
        }  
        else  
        {  
            return null;  
        }  
    }  

    //创建访问验证对象并调用其Validate()方法实现身份验证  
    public bool validate(string userId)  
    {  
        validator = new AccessValidator();  
        return validator.Validate(userId);  
    }  

    //创建日志记录对象并调用其Log()方法实现日志记录  
    public void log(string userId)  
    {  
        logger = new Logger();  
        logger.Log(userId);  
    }  
} 

(6) 配置文件App.config,在计划文件中贮存了代理宗旨类类名。

<?xml version="1.0" encoding="utf-8" ?>  
<configuration>  
  <appSettings>  
    <add key="proxy" value="ProxySample.ProxySearcher"/>  
  </appSettings>  
</configuration>

(7) Client:客户端测试类

class Client  
{  
    public static void main(String[] args)  
    {  
        //读取配置文件  
        String proxy = ConfigurationManager.AppSettings["proxy"];  

        //反射生成对象,针对抽象编程,客户端无须分辨真实主题类和代理类  
        Searcher searcher = (Searcher)ProxyXMLUtil.getBean();  

        String result = searcher.doSearch("杨过", "玉女心经");   
    }  
} 

15.3.4 结果及分析

编译并运转程序,输出结果如下:

在数据库中验证用户'杨过'是否是合法用户?
'杨过'登录成功!
用户'杨过'使用关键词'玉女心经'查询商务信息!
更新数据库,用户'杨过'查询次数加1!

本实例是保安代理和智能引用代理的利用实例,在代理类ProxySearcher中落到实处对真正核心类的权位控制和引用计数,若是须要在访问真正核心时增添新的访问控制机制和新效用,只需扩大2个新的代理类,再修改配置文件,在客户端代码中使用激增代理类即可,源代码无须修改,符合开闭原则。

代办分类

  • 长距离代理(Remote
    Proxy):为二个身处区其余地方空间的对象提供三个本地的代理对象,这些不相同的地点空间可以是在同等台主机中,也不过在另一台主机中,远程代理又称之为大使(Ambassador)。

    澳门威尼斯人网址 6

  • 虚拟代理(Virtual
    Proxy):假若急需制造2个能源消耗较大的目的,先创设二个消耗相对较小的靶子来表示,真实对象只在急需时才会被真正创立。

  • 保安代理(Protect
    Proxy):控制对二个对象的拜访,可以给差其他用户提供差别级其他应用权力。

  • 缓冲代理(Cache
    Proxy):为某一个对象操作的结果提供临时的仓储空间,以便多个客户端可以共享那几个结果。

  • 智能引用代理(斯马特 Reference
    Proxy):当三个对象被引用时,提供部分十分的操作,例如将目的被调用的次数记录下来等。

15.1 代理格局概述

       近期,代购已日趋成为电子商务的3个重点分支。何谓代购,简单的讲就是找人帮忙购买所必要的商品,当然你只怕须求向实践代购的人付出一定的开销。代购常常分为两体系型:一种是因为在地头买不到某件商品,又或然是因为当地那件商品的价位比其它地域的贵,因而托人在其他地区照旧海外购置该商品,然后经过快递发货只怕直接带走回来;还有一种代购,由于消费者对想要购买的商品有关音讯的不够,自已无力回天鲜明其实际价值而又不想被商户宰,只能委托中介机构帮其讲价或为其代买。代购网站为此应运而生,它为买主提供在线的代购服务,若是看中某海外购物网站上的商品,可以登录代购网站填写代购单并给付,代购网站会拉扯拓展购买然后通过快递集团将商品发送给消费者。商品代购进度如图15-1所示:

澳门威尼斯人网址 7

图15-1 商品代购示意图

       在软件开发中,也有一种设计格局可以提供与代购网站类似的功用。由于有些原因,客户端不想或不可以直接访问1个目标,此时得以经过3个叫做“代理”的别人来落成直接访问,该方案对应的设计方式被叫作代理情势。

       代理方式是一种采取很宽泛的结构型设计情势,而且转移格局格外多,常见的代理格局包罗远程代理、保养代理、虚拟代理、缓冲代理、智能引用代理等,后边将学习那一个不一致的代办格局。

       代理情势定义如下:

 

代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

Proxy Pattern: Provide a surrogate or placeholder for another object to control access to it.

 

      
代理情势是一种对象结构型格局。在代理格局中引入了三个新的代理对象,代理对象在客户端对象和对象对象时期起到中介的功用,它去掉客户不可以收看的始末和劳务如故增添客户需求的附加的新劳动。

 

15.2 代理情势协会与贯彻

设计格局之代理形式(三)

15.4 远程代理

长途代理(Remote
Proxy)是一种常用的代理格局,它使得客户端程序可以访问在长途主机上的对象,远程主机大概具有更好的揣测质量与处理速度,可以便捷响应并处理客户端的请求。远程代理可以将网络的细节隐藏起来,使得客户端不必考虑互连网的留存。客户端完全能够认为被代理的长距离业务对象是在本土而不是在长距离,而远程代理对象承担了多数的互联网通讯工作,并负担对长途业务方法的调用。

长距离代理示意图如图15-5所示,客户端对象不能一直访问远程主机中的业务对象,只好采用直接访问的主意。远程业务对象在本土主机中有多少个代理对象,该代理对象承担对长距离业务对象的访问和互连网通讯,它对于客户端对象而言是晶莹的。客户端无须关怀完结具体事务的是何人,只需求听从服务接口所定义的法子直接与本地主机中的代理对象交互即可。

澳门威尼斯人网址 8

图15-5 远程代理示意图

扩展

在基于.NET平台的分布式技术,例如DCOM(Distribute Component Object
Model,分布式组件对象模型)、Web
Service中,都利用了中距离代理形式,咱们可以查看有关资料进行扩大学习。

15.5 虚拟代理

虚拟代理(Virtual
Proxy)也是一种常用的代办情势,对于有个别占据系统财富较多照旧加载时间较长的靶子,可以给那个目的提供二个虚拟代理。在实事求是对象成立成功在此以前虚拟代理扮演真实对象的替罪羊,而当真正对象创制之后,虚拟代理将用户的乞请转载给真实对象。

常见,在偏下二种景况下得以考虑使用虚拟代理:

(1)
由于目的自作者的纷纭可能网络等原因导致3个目标急需较长的加载时间,此时可以用二个加载时间相对较短的代理对象来表示真实对象。平常在贯彻时得以结合二十四线程技术,一个线程用于显示代理对象,其余线程用于加载真实对象。那种虚拟代理形式可以使用在程序运营的时候,由于创制代理对象在时刻和拍卖复杂度上要有数创立真实对象,由此,在先后运转时,可以用代理对象代替真实对象初叶化,大大加快了系统的起步时间。当必要动用真实对象时,再经过代理对象来引用,而那时实际对象或许曾经打响加载达成,可以收缩用户的等候时间。

(2)
当3个对象的加载拾叁分消耗系统能源的时候,也相当适合使用虚拟代理。虚拟代理可以让那2个占据多量内存或处理起来极度复杂的对象推迟到应用它们的时候才成立,而在此此前用三个相对来说占用能源较少的代理对象来表示真实对象,再通过代办对象来引用真实对象。为了节约内存,在首回引用真实对象时再创设对象,并且该目的可被一再收录,在随后每一趟访问时索要检测所需对象是还是不是已经被创建,因而在访问该目的时索要开展存在性检测,那要求花费一定的体系时间,可是足以节本省存空间,那是一种用时间换取空间的做法。

不论是以上哪一种情状,虚拟代理都以用三个“虚假”的代办对象来表示真实对象,通过代理对象来直接引用真实对象,可以在肯定程度上增强系统的性质。

15.6 缓冲代理

缓冲代理(Cache
Proxy)也是一种比较常用的代办形式,它为某多少个操作的结果提供一时半刻的缓存存储空间,以便在继续使用中可见共享这个结果,从而可以幸免某个方法的再度执行,优化系统质量。

在微软以身作则项目PetShop 4.0的政工逻辑层(Business Logic Layer,
BLL)中定义了Product、Category、Item等类,它们封装了相关的作业方法,用于调用数据访问层(Data
Access Layer,
DAL)对象访问数据库,以博得有关数据。为了改正系统个性,PetShop
4.0为这一个已毕形式扩充缓存机制,引入壹个新的靶子去决定原来的BLL业务逻辑对象,这一个新的目的对应于代理形式中的代理对象。在引入代理形式后,落成了在缓存级别上对工作对象的包裹,增强了对作业对象的操纵,如若要求拜访的多寡在缓存中曾经存在,则无须再重复执行获取数据的法子,直接重临存储在缓存中的数据即可。由于原有业务对象(真实对象)和新增代理对象揭露在外的主意是平等的,因此对于调用方即客户端而言,调用代理对象与忠实对象并没有实质的分别。

这几个新引入的代理类包罗ProductDataProxy、CategoryDataProxy和ItemDataProxy等。上面以PetShop.BLL.Product业务对象为例进行认证,PetShop
4.0为其建立了代办对象ProductDataProxy,并在ProductDataProxy的GetProductsByCategory()方法中调用了工作逻辑层Product类的GetProductsByCategory()方法,同时增加了缓存机制。如图15-6所示:

澳门威尼斯人网址 9

图15-6 PetShop4.0缓存代理示意图

在ProductDataProxy类中存在如下代码片段:

public static class ProductDataProxy  
{  
    private static readonly int productTimeout = int.Parse(ConfigurationManager.AppSettings ["ProductCacheDuration"]);  
    private static readonly bool enableCaching = bool.Parse(ConfigurationManager. AppSettings["EnableCaching"]);   

    public static IList GetProductsByCategory(string category)  
    {          
        Product product = new Product();  

        //如果缓存被禁用,则直接通过product对象来获取数据  
         if (!enableCaching)  
        {  
            return product.GetProductsByCategory(category);  
        }  

        string key = "product_by_category_" + category;  
        //从缓存中获取数据  
         IList data = (IList )HttpRuntime.Cache[key];    

        //如果缓存中没有数据则执行如下代码  
          if (data == null)  
        {              
          data = product.GetProductsByCategory(category);              
          //通过工厂创建AggregateCacheDependency对象  
            AggregateCacheDependency cd = DependencyFacade.GetProductDependency ();   
          //将数据存储在缓存中,并添加必要的AggregateCacheDependency对象  
            HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(product Timeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);   
        }  
        return data;  
    }  
    // ……  
}

在上述代码中,AggregateCacheDependency是从.NET Framework
2.0开首新增的三个类,它肩负监视看重项对象的聚合。当那些集合中的任意一个借助项对象爆发转移时,该重视项对象对应的缓存对象都将被自动移除。在此不对AggregateCacheDependency进行详尽表达,大家可以查阅相关资料举办扩充学习。
与事务逻辑层Product对象的GetProductsByCategory()方法比较,上述代码扩大了缓存机制。当缓存内不设有相关数据项时,则直接调用业务逻辑层Product的GetProductsByCategory()方法来获取数据,并将其与相应的AggregateCacheDependency对象一起存储在缓存中。在ProductDataProxy类的每二个事务方法中都实例化了Product类,再调用Product类的对应措施,由此ProductDataProxy与Product之间属于看重关系,那是专业代理格局的一种变形,可以根据规范代理方式对其进展校对,包含引入高层的架空接口。

示例

  某软件商店承接了某音信咨询公司的收款商务新闻查询系统的开发职务,该系统的着力须求如下:
(1)
在开展商务消息查询此前用户必要经过身份验证,唯有合法用户才可以使用该查询系统;
(2)
在开展商务音信查询时系统须要记录查询日志,以便根据查询次数收取查询用度。
  该软件集团开发人士已形成了商务新闻查询模块的开发职责,现希望可以以一种松耦合的艺术向原有系统增加身份验证和日志记录功效,客户端代码可以无差别地对待原始的商务音讯查询模块和充实新成效之后的商务消息查询模块,而且只怕在今后还要在该新闻查询模块中追加部分新的法力。

澳门威尼斯人网址 10

澳门威尼斯人网址 11

using System;  

namespace ProxySample  
{  
    class AccessValidator  
    {  
        //模拟实现登录验证  
        public bool Validate(string userId)   
        {  
            Console.WriteLine("在数据库中验证用户'" + userId + "'是否是合法用户?");  
            if (userId.Equals("杨过")) {  
                Console.WriteLine("'{0}'登录成功!",userId);  
                return true;  
            }  
            else {  
                Console.WriteLine("'{0}'登录失败!", userId);  
                return false;  
            }  
        }  
    }  
}  

using System;  

namespace ProxySample  
{  
    class Logger  
    {  
        //模拟实现日志记录  
        public void Log(string userId) {  
            Console.WriteLine("更新数据库,用户'{0}'查询次数加1!",userId);  
        }  
    }  
} 

namespace ProxySample  
{  
    interface Searcher  
    {  
        string DoSearch(string userId, string keyword);  
    }  
}  

using System;  

namespace ProxySample  
{  
    class RealSearcher : Searcher  
    {  
        //模拟查询商务信息  
        public string DoSearch(string userId, string keyword) {  
            Console.WriteLine("用户'{0}'使用关键词'{1}'查询商务信息!",userId,keyword);  
            return "返回具体内容";  
        }  
    }  
}  

namespace ProxySample  
{  
    class ProxySearcher : Searcher  
    {  
        private RealSearcher searcher = new RealSearcher(); //维持一个对真实主题的引用  
        private AccessValidator validator;  
        private Logger logger;  

        public string DoSearch(string userId, string keyword)  
        {  
            //如果身份验证成功,则执行查询  
            if (this.Validate(userId))  
            {  
                string result = searcher.DoSearch(userId, keyword); //调用真实主题对象的查询方法  
                this.Log(userId); //记录查询日志  
                return result; //返回查询结果  
            }  
            else  
            {  
                return null;  
            }  
        }  

        //创建访问验证对象并调用其Validate()方法实现身份验证  
        public bool Validate(string userId)  
        {  
            validator = new AccessValidator();  
            return validator.Validate(userId);  
        }  

        //创建日志记录对象并调用其Log()方法实现日志记录  
        public void Log(string userId)  
        {  
            logger = new Logger();  
            logger.Log(userId);  
        }  
    }  
}  

<?xml version="1.0" encoding="utf-8" ?>  
<configuration>  
  <appSettings>  
    <add key="proxy" value="ProxySample.ProxySearcher"/>  
  </appSettings>  
</configuration> 

using System;  
using System.Configuration;  
using System.Reflection;  

namespace ProxySample  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            //读取配置文件  
            string proxy = ConfigurationManager.AppSettings["proxy"];  

            //反射生成对象,针对抽象编程,客户端无须分辨真实主题类和代理类  
            Searcher searcher;  
            searcher = (Searcher)Assembly.Load("ProxySample").CreateInstance(proxy);  

            String result = searcher.DoSearch("杨过", "玉女心经");  
            Console.Read();  
        }  
    }  
}  

15.2.1 形式结构

     
代理格局的社团比较不难,其中央是代理类,为了让客户端可以一致性地对待真实对象和代办对象,在代理格局中引入了抽象层,代理格局社团如图15-2所示:

澳门威尼斯人网址 12

 

图15-2 代理格局结构图

       由图15-2可以,代理情势涵盖如下八个角色:

       (1)
Subject(抽象大旨角色):
它注脚了真格核心和代办宗旨的一起接口,那样一来在任何利用真实主旨的地方都足以利用代理主旨,客户端寻常要求针对抽象宗旨剧中人物举行编程。

       (2)
Proxy(代理主旨脚色):
它富含了对真正大旨的引用,从而可以在任何时候操作实际核心对象;在代理焦点角色中提供两个与诚实主旨角色一样的接口,以便在别的时候都足以代替真实焦点;代理宗旨角色还足以决定对真实核心的行使,负责在急需的时候成立和删除真实核心对象,并对实在核心对象的使用加以约束。经常,在代理焦点角色中,客户端在调用所引述的实际核心操作以前或将来还索要履行其余操作,而不光是只是调用真实大旨对象中的操作。

       (3)
RealSubject(真实核心角色):
它定义了代理剧中人物所代表的真人真事对象,在真实主旨剧中人物中落实了诚实的事务操作,客户端可以透过代办主旨剧中人物直接调用真实主旨角色中定义的操作。

 

设计方式之代理情势(四)

15.7 代理形式作用与适用场景

代办方式是常用的结构型设计形式之一,它为对象的直接访问提供了一个解决方案,可以对目的的访问举办支配。代理形式类型较多,其中长途代理、虚拟代理、尊敬代理等在软件开发中运用越发广阔。

15.7.1 形式亮点

代理情势的一块儿优点如下:

(1) 能够协调调用者和被调用者,在早晚水准上下落了系统的耦合度。

(2)
客户端可以针对抽象主旨角色进行编程,扩张和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可增添性。

除此以外,不一致类其他代理情势也装有独特的优点,例如:

(1)
远程代理为位于多个不等地方空间对象的拜访提供了一种完结机制,可以将一部分消耗财富较多的目标和操作移至品质更好的处理器上,进步系统的共同体运转效用。

(2)
虚拟代理通过3个消耗财富较少的对象来表示2个消耗电源较多的靶子,可以在必然水平上节省系统的周转开支。

(3)
缓冲代理为某3个操作的结果提供权且的缓存存储空间,以便在后续使用中可以共享这一个结果,优化系统性子,减弱执行时间。

(4)
爱慕代理可以控制对贰个目的的造访权限,为不相同用户提供差别级其余采用权力。

15.7.2 方式缺点

代办形式的严重性缺点如下:

(1)
由于在客户端和实事求是宗旨之间扩充了代理对象,因此有些类其余代办情势或然会招致请求的处理速度变慢,例如保养代理。

(2)
已毕代理格局必要极度的干活,而且有个别代理形式的完毕进度较为复杂,例如远程代理。

15.7.3 情势适用场景

代理方式的档次较多,不一致门类的代理情势有两样的得失,它们应用于差其他场地:

(1) 当客户端对象急需拜访远程主机中的对象时得以选取远程代理。

(2)
当必要用2个消耗财富较少的靶子来代表3个消耗电源较多的目的,从而下落系统开发、裁减运转时刻时得以利用虚拟代理,例如多少个目的急需相当长日子才能成功加载时。

(3)
当须求为某三个被一再造访的操作结果提供二个权且存储空间,以供七个客户端共享访问这么些结果时方可运用缓冲代理。通过行使缓冲代理,系统无须在客户端每三回访问时都再也履行操作,只需直接从权且缓冲区获取操作结果即可。

(4)
当要求控制对多个对象的访问,为不一样用户提供差别级其他拜会权限时方可动用敬服代理。

(5)
当须要为3个目的的拜访(引用)提供一些额外的操作时能够使用智能引用代理。

练习
1 Windows操作系统中的应用程序疾速方式是( )格局的采用实例。
A. 代理 (Proxy) B. 组合 (Composite)
C. 装饰 (Decorator) D. 外观 (Facade)

答:A (快速格局做代理,客户无需关系具体落到实处)

2
结束学业生经过职业介绍所找工作,请问该进度包涵了哪一种设计情势,绘制相应的类图。

答:代理形式。职业介绍所作为店铺的代办。

澳门威尼斯人网址 13

结束学业生通过职业介绍所找工作类图

3
在某应用软件中必要记录业务方法的调用日志,在不改动现有业务类的根底上为每三个类提供壹个日记记录代理类,在代理类中输出日志,如在工作方法Method()调用以前输出“方法Method()被调用,调用时间为2011-11-5
10:10:10”,调用之后即使没有抛卓殊则输出“方法Method()调用成功”,否则输出“方法Method()调用战败”。在代理类中调用真实业务类的事情方法,使用代理格局设计该日志记录模块的布局,绘制类图并使用Java语言编程模拟完结。

答:

澳门威尼斯人网址 14

日志记录模块的构造

4
某软件商店欲开发一款基于C/S的互连网图片查看器,具体效果描述如下:用户只需在图片查看器中输入网页U中华VL,程序将活动将该网页全数图片下载到地头,考虑到稍微网页图片比较多,而且一些图片文件相比大,由此将先以图标的法子展现图片,差距类其他图形应用不相同的图标,并且在图标上面标注该图形的公文名,用户单击图标后可查阅真正的图样,界面效果如图15-7所示。试使用虚拟代理格局设计并贯彻该图片查看器。(注:可以组合四线程机制,使用3个线程显示小图标,同时起步另三个线程在后台加载原图。)

澳门威尼斯人网址 15

图15-7 图片查看器界面效果图

【友情提示:提出大家有时光的话把这几个演习都做一做,不平常欢迎商讨!】

磨炼会在我的github上做掉

总结

重中之重优点:
(1) 可以协调调用者和被调用者,在一定水平上跌落了系统的耦合度。
(2)
客户端可以本着抽象宗旨剧中人物进行编程,扩张和转换代理类无须修改源代码,符合开闭原则,系统具备较好的一帆风顺和可伸张性。
  不一致类型的代理方式也颇具特种的独到之处,例如:
(1)
长途代理为放在多个不等地点空间对象的走访提供了一种已毕机制,可以将部分消耗财富较多的对象和操作移至品质更好的处理器上,进步系统的完好运转效能。
(2)
虚拟代理透过三个消耗电源较少的对象来表示三个消耗电源较多的靶子,可以在一定水平上节省系统的运维用度。
(3)
缓冲代理为某1个操作的结果提供一时的缓存存储空间,以便在三番三次使用中可见共享那些结果,优化系统品质,缩小执行时间。
(4)
护卫代理可以控制对三个目的的拜访权限,为不一样用户提供差别级其他施用权力。
关键缺点:
(1)
由于在客户端和实事求是大旨之间增添了代办对象,由此某些项目的代理形式恐怕会促成请求的处理速度变慢,例如:珍爱代理。
(2)
完成代理方式须求额外的行事,而且有个别代理情势的贯彻进程较为复杂,例如:远程代理。

15.2.2 方式达成

      
代理情势的构造图相比不难,不过在真正的接纳和落到实处进度中要复杂很多,尤其是代理类的统筹和兑现。

      
抽象主旨类注脚了真格的主题类和代理类的国有艺术,它可以是接口、抽象类或具体类,客户端针对抽象大旨类编程,一致性地对待真实宗旨和代办大旨,典型的抽象核心类代码如下:

abstract class Subject  
{  
    public abstract void Request();  
}  

开诚相见宗旨类继承了抽象核心类,提供了政工方法的有血有肉落到实处,其独立代码如下:

class RealSubject : Subject  
{  
    public override void Request()  
    {  
        //业务方法具体实现代码  
    }  
}  

代理类也是纸上谈九黎氏旨类的子类,它维持2个对实际主题对象的引用,调用在实事求是主旨中达成的工作方法,在调用时方可在本来工作方法的根底上附加一些新的章程来对职能拓展扩大或约束,最不难易行的代理类完成代码如下:

class Proxy : Subject  
{  
    private RealSubject realSubject = new RealSubject(); //维持一个对真实主题对象的引用  

    public void PreRequest()   
    {  
        …...  
    }  

    public override void Request()   
    {  
        PreRequest();  
        realSubject.Request(); //调用真实主题对象的方法  
         PostRequest();  
    }  

    public void PostRequest()   
    {  
        ……  
    }  
}  

在实际支付进程中,代理类的兑现比上述代码要复杂很多,代理情势依据其目的和完毕格局差异可分为很多类型,其中常用的两种代理方式大致表明如下:

       (1) 远程代理(Remote
Proxy)
为三个放在差其余地址空间的靶子提供2个地面的代理对象,这几个不相同的地点空间可以是在相同台主机中,也不过在另一台主机中,远程代理又叫做大使(Ambassador)。

       (2) 虚拟代理(Virtual
Proxy):如若需求创立2个财富消耗较大的目的,先创立壹个消耗绝对较小的目的来代表,真实对象只在须求时才会被真正创设。

       (3) 敬重代理(Protect
Proxy)
控制对1个目标的访问,可以给区其余用户提供差别级其他施用权限。

       (4) 缓冲代理(Cache
Proxy)
为某贰个目的操作的结果提供权且的蕴藏空间,以便多个客户端能够共享这一个结果。

       (5) 智能引用代理(斯马特 Reference
Proxy)
当3个对象被引述时,提供一些附加的操作,例如将目的被调用的次数记录下来等。

      
在那几个常用的代理形式中,某个代理类的设计分外复杂,例如远程代理类,它包裹了底层互联网通信和对长途对象的调用,其落到实处相比复杂。

适用场景

(1) 当客户端对象急需拜访远程主机中的对象时方可运用长途代理
(2)
当须要用1个消功耗源较少的靶子来表示二个消耗电源较多的对象,从而下落系统开发、减少运维时刻时可以动用编造代理,例如:三个对象须要非常长日子才能一气浑成加载时。
(3)
当须求为某二个被反复造访的操作结果提供二个暂且存储空间,以供多少个客户端共享访问那个结果时得以运用缓冲代理。通过应用缓冲代理,系统无须在客户端每趟访问时都再度履行操作,只需直接从一时缓冲区获取操作结果即可。
(4)
当须求控制对多少个目的的拜会,为不一致用户提供不相同级其余造访权限时可以应用珍惜代理
(5)
当需求为3个对象的走访(引用)提供一些外加的操作时得以使用智能引用代理

15.3 代理形式应用实例

       上面通过三个利用实例来进一步学习和透亮代理形式。

       1. 实例证实

 

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

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

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

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

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

 

       2. 实例分析及类图

      
通过分析,可以应用一种直接访问的方法来落到实处该商务消息查询系统的安插,在客户端对象和消息查询对象时期扩充1个代理对象,让代理对象来兑出现份验证和日志记录等作用,而无须直接对原有的商务新闻查询对象开展改动,如图15-3所示:

澳门威尼斯人网址 16

图15-3 商务音讯查询系统设计方案示意图

       在图15-3中,客户端对象通过代办对象直接访问具有商务新闻查询功效的实际对象,在代理对象中除了调用真实对象的商务消息查询功用外,还伸张了身份验证和日志记录等作用。使用代理方式设计该商务音信查询系统,结构图如图15-4所示。

澳门威尼斯人网址 17

图15-4 商务消息查询系统结构图

      
在图15-4中,业务类AccessValidator用于讲明用户地点,业务类Logger用于记录用户查询日志,Searcher充当抽象大旨角色,RealSearcher充当真实大旨角色,ProxySearcher充当代理大旨角色。

       3. 实例代码

       (1)
AccessValidator:身份验证类,业务类,它提供形式Validate()来落到实处身份验证。

using System;  

namespace ProxySample  
{  
    class AccessValidator  
    {  
        //模拟实现登录验证  
        public bool Validate(string userId)   
        {  
            Console.WriteLine("在数据库中验证用户'" + userId + "'是否是合法用户?");  
            if (userId.Equals("杨过")) {  
                Console.WriteLine("'{0}'登录成功!",userId);  
                return true;  
            }  
            else {  
                Console.WriteLine("'{0}'登录失败!", userId);  
                return false;  
            }  
        }  
    }  
}  

  (2) Logger:日志记录类,业务类,它提供格局Log()来保存日志。

using System;  

namespace ProxySample  
{  
    class Logger  
    {  
        //模拟实现日志记录  
        public void Log(string userId) {  
            Console.WriteLine("更新数据库,用户'{0}'查询次数加1!",userId);  
        }  
    }  
}  

 (3) Searcher:抽象查询类,充当抽象核心角色,它表明了DoSearch()方法。

namespace ProxySample  
{  
    interface Searcher  
    {  
        string DoSearch(string userId, string keyword);  
    }  
}  

  (4)
RealSearcher:具体查询类,充当真实主旨角色,它落成查询成效,提供格局DoSearch()来询问音讯。

//RealSearcher.cs  
using System;  

namespace ProxySample  
{  
    class RealSearcher : Searcher  
    {  
        //模拟查询商务信息  
        public string DoSearch(string userId, string keyword) {  
            Console.WriteLine("用户'{0}'使用关键词'{1}'查询商务信息!",userId,keyword);  
            return "返回具体内容";  
        }  
    }  
}  

(5)
ProxySearcher:代理查询类,充当代理宗旨角色,它是查询代理,维持了对RealSearcher对象、AccessValidator对象和Logger对象的引用。

//ProxySearcher.cs  
namespace ProxySample  
{  
    class ProxySearcher : Searcher  
    {  
        private RealSearcher searcher = new RealSearcher(); //维持一个对真实主题的引用  
        private AccessValidator validator;  
        private Logger logger;  

        public string DoSearch(string userId, string keyword)  
        {  
            //如果身份验证成功,则执行查询  
            if (this.Validate(userId))  
            {  
                string result = searcher.DoSearch(userId, keyword); //调用真实主题对象的查询方法  
                this.Log(userId); //记录查询日志  
                return result; //返回查询结果  
            }  
            else  
            {  
                return null;  
            }  
        }  

        //创建访问验证对象并调用其Validate()方法实现身份验证  
        public bool Validate(string userId)  
        {  
            validator = new AccessValidator();  
            return validator.Validate(userId);  
        }  

        //创建日志记录对象并调用其Log()方法实现日志记录  
        public void Log(string userId)  
        {  
            logger = new Logger();  
            logger.Log(userId);  
        }  
    }  
}  

(6) 配置文件App.config,在安插文件中蕴藏了代理主题类类名。

  1. <?xml version=”1.0″ encoding=”utf-8″ ?>  
  2. <configuration>  
  3.   <appSettings>  
  4.     <add key=”proxy” value=”ProxySample.ProxySearcher”/>  
  5.   </appSettings>  
  6. </configuration>  

(7) Program:客户端测试

//Program.cs  
using System;  
using System.Configuration;  
using System.Reflection;  

namespace ProxySample  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            //读取配置文件  
            string proxy = ConfigurationManager.AppSettings["proxy"];  

            //反射生成对象,针对抽象编程,客户端无须分辨真实主题类和代理类  
            Searcher searcher;  
            searcher = (Searcher)Assembly.Load("ProxySample").CreateInstance(proxy);  

            String result = searcher.DoSearch("杨过", "玉女心经");  
            Console.Read();  
        }  
    }  
}  

4. 结果及分析

        编译并运营程序,输出结果如下:

 

数据库中验证用户’杨过’是否是合法用户?

‘杨过’登录成功!

用户’杨过’使用关键词’玉女心经’查询商务信息!

更新数据库,用户’杨过’查询次数加1!

 

      
本实例是保安代理智能引用代理的采用实例,在代理类ProxySearcher中完毕对实事求是宗旨类的权力控制和引用计数,若是急需在拜访真正主题时扩充新的访问控制机制和新职能,只需追加一个新的代理类,再修改配置文件,在客户端代码中行使新增代理类即可,源代码无须修改,符合开闭原则。

15.4 远程代理

      远程代理(Remote
Proxy)
是一种常用的代办情势,它使得客户端程序可以访问在中距离主机上的靶子,远程主机可能拥有更好的盘算质量与处理速度,可以高速响应并拍卖客户端的乞请。远程代理可以将互联网的细节隐藏起来,使得客户端不必考虑互联网的留存。客户端完全可以认为被代理的中距离业务对象是在本地而不是在中距离,而远程代理对象承担了绝一大半的互联网通讯工作,并肩负对长途业务方法的调用。

      
远程代理示意图如图15-5所示,客户端对象不可以一直访问远程主机中的业务对象,只能够选拔直接访问的章程。远程业务对象在本土主机中有2个代理对象,该代理对象承担对长距离业务对象的造访和互联网通讯,它对于客户端对象而言是透明的。客户端无须关切落成具体工作的是哪个人,只需要坚守服务接口所定义的办法直接与当地主机中的代理对象交互即可。

澳门威尼斯人网址 18

图15-5 远程代理示意图

      在基于.NET平台的分布式技术,例如DCOM(Distribute Component Object
Model,分布式组件对象模型)、Web
Service中,都拔取了中距离代理方式,大家能够查阅有关材质举办扩大学习。

 

15.5 虚拟代理

       虚拟代理(Virtual
Proxy)
也是一种常用的代理格局,对于一些据为己有系统能源较多或然加载时间较长的目标,可以给那几个目的提供2个虚构代理。在真正对象创制成功以前虚拟代理扮演真实对象的替身,而当实际对象创制之后,虚拟代理将用户的伏乞转载给真实对象。

       常常,在以下两种境况下得以考虑接纳虚拟代理:

        (1) 由于目标自笔者的错综复杂大概网络等原因促成一个对象须要较长的加载时间,此时得以用一个加载时间相对较短的代办对象来代表真实对象。日常在贯彻时方可构成多线程技术,一个线程用于体现代理对象,其他线程用于加载真实对象。那种虚拟代理情势可以行使在先后运维的时候,由于创制代理对象在岁月和处理复杂度上要不难创制真实对象,因而,在程序运转时,可以用代理对象代替真实对象初阶化,大大加快了系统的运维时间。当需求拔取真实对象时,再通过代办对象来引用,而那时候实在对象恐怕曾经打响加载完成,能够减弱用户的等候时间。

      (2) 当二个目标的加载十一分消耗系统财富的时候,也非凡适合使用虚拟代理。虚拟代理可以让那3个占用多量内存或拍卖起来非凡复杂的目的推迟到应用它们的时候才创制,而在此之前用一个绝对来说占用能源较少的代办对象来代表真实对象,再通过代办对象来引用真实对象。为了省去内存,在首先次引用真实对象时再创造对象,并且该目的可被频仍引用,在事后每一回访问时要求检测所需对象是不是早已被创建,因而在访问该对象时需求展开存在性检测,那亟需消耗一定的系统时间,不过可以节约内存空间,那是一种用时间换取空间的做法。

      
无论是以上哪一类情状,虚拟代理都以用1个“虚假”的代办对象来表示真实对象,通过代理对象来直接引用真实对象,可以在必然水平上压实系统的性质。

 

15.6 缓冲代理

       缓冲代理(Cache
Proxy)
也是一种较为常用的代办形式,它为某多少个操作的结果提供临时的缓存存储空间,以便在接二连三使用中能够共享那一个结果,从而得以幸免有些方法的重复执行,优化系统品质。

       在微软示范项目PetShop 4.0的事情逻辑层(Business Logic Layer,
BLL)中定义了Product、Category、Item等类,它们封装了连带的政工方法,用于调用数据访问层(Data
Access Layer,
DAL)对象访问数据库,以拿到有关数据。为了改正系统特性,PetShop
4.0为这么些完毕方式增加缓存机制,引入1个新的对象去决定原来的BLL业务逻辑对象,这一个新的目的对应于代理方式中的代理对象。在引入代理方式后,落成了在缓存级别上对业务对象的包装,增强了对事情对象的支配,借使急需拜访的多少在缓存中曾经存在,则无须再重复执行获取数据的主意,直接重临存储在缓存中的数据即可。由于原有业务对象(真实对象)和新增代理对象暴露在外的艺术是一致的,由此对于调用方即客户端而言,调用代理对象与忠实对象并不曾精神的界别。

      
这一个新引入的代理类包含ProductDataProxy、CategoryDataProxy和ItemDataProxy等。上面以PetShop.BLL.Product业务对象为例进行说明,PetShop
4.0为其创设了代理对象ProductDataProxy,并在ProductDataProxy的GetProductsByCategory()方法中调用了工作逻辑层Product类的GetProductsByCategory()方法,同时增加了缓存机制。如图15-6所示:

澳门威尼斯人网址 19

图15-6 PetShop4.0缓存代理示意图

       在ProductDataProxy类中留存如下代码片段:

public static class ProductDataProxy  
{  
    private static readonly int productTimeout = int.Parse(ConfigurationManager.AppSettings ["ProductCacheDuration"]);  
    private static readonly bool enableCaching = bool.Parse(ConfigurationManager. AppSettings["EnableCaching"]);   

    public static IList GetProductsByCategory(string category)  
    {          
        Product product = new Product();  

        //如果缓存被禁用,则直接通过product对象来获取数据  
         if (!enableCaching)  
        {  
            return product.GetProductsByCategory(category);  
        }  

        string key = "product_by_category_" + category;  
        //从缓存中获取数据  
         IList data = (IList )HttpRuntime.Cache[key];    

        //如果缓存中没有数据则执行如下代码  
          if (data == null)  
        {              
          data = product.GetProductsByCategory(category);              
          //通过工厂创建AggregateCacheDependency对象  
            AggregateCacheDependency cd = DependencyFacade.GetProductDependency ();   
          //将数据存储在缓存中,并添加必要的AggregateCacheDependency对象  
            HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(product Timeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);   
        }  
        return data;  
    }  
        ……  
}  

在上述代码中,AggregateCacheDependency是从.NET Framework
2.0开端新增的1个类,它承受监视正视项对象的联谊。当那些集合中的任意三个借助项对象发生转移时,该正视项对象对应的缓存对象都将被电动移除。在此不对AggregateCacheDependency进行详细表明,我们能够查看有关质地举行扩张学习。

      
与作业逻辑层Product对象的GetProductsByCategory()方法比较,上述代码增添了缓存机制。当缓存内不设有相关数据项时,则直接调用业务逻辑层Product的GetProductsByCategory()方法来获取数据,并将其与相应的AggregateCacheDependency对象一起存储在缓存中。在ProductDataProxy类的每一个政工方法中都实例化了Product类,再调用Product类的呼应措施,由此ProductDataProxy与Product之间属于器重关系,那是正经代理形式的一种变形,能够依据专业代理情势对其举行改正,包含引入高层的画饼充饥接口。

15.7 代理形式效率与适用场景

      
代理方式是常用的结构型设计形式之一,它为目标的直接访问提供了二个消除方案,可以对指标的造访举办支配。代理方式类型较多,其中长途代理、虚拟代理、珍重代理等在软件开发中使用尤其广阔。

 

15.7.1 形式亮点

       代理形式的一路优点如下:

       (1) 能够协调调用者和被调用者,在必然水平上降低了系统的耦合度。

      
(2) 客户端可以本着抽象宗旨剧中人物进行编程,扩张和更换代理类无须修改源代码,符合开闭原则,系统具有较好的八面玲珑和可扩充性。

澳门威尼斯人网址,       其它,差异体系的代理格局也享有特种的亮点,例如:

      
(1) 长距离代理为身处三个例外地方空间对象的走访提供了一种已毕机制,可以将某个消功耗源较多的靶子和操作移至品质更好的微机上,升高系统的全体运转成效。

      
(2) 编造代理通过一个消耗财富较少的目标来表示1个消功耗源较多的靶子,可以在任其自然水平上节省系统的运营费用。

      
(3) 缓冲代理为某一个操作的结果提供临时的缓存存储空间,以便在持续使用中可见共享那几个结果,优化系统脾性,减少执行时间。

      
(4) 保安代理可以控制对二个目的的访问权限,为差别用户提供不相同级其他拔取权限。

 

15.7.2 方式缺点

       代理方式的要害症结如下:

      
(1) 由于在客户端和真实性宗旨之间增添了代办对象,由此有个别项目的代理情势或然会招致请求的处理速度变慢,例如爱惜代理。

      
(2) 已毕代理情势须要非常的做事,而且有些代理格局的完毕进程比较复杂,例如远程代理。

 

15.7.3 形式适用场景

      
代理形式的档次较多,不一致品类的代理情势有区其余利弊,它们应用于不一致的场馆:

       (1) 当客户端对象急需拜访远程主机中的对象时方可运用远程代理。

      
(2) 当必要用1个消耗财富较少的靶子来表示二个消耗财富较多的对象,从而下落系统开发、缩小运维时刻时得以行使虚拟代理,例如3个目的急需十分长日子才能做到加载时。

      
(3) 当须求为某一个被一再造访的操作结果提供一个目前存储空间,以供七个客户端共享访问那几个结果时能够选用缓冲代理。通过使用缓冲代理,系统无须在客户端每三回访问时都再度履行操作,只需间接从一时缓冲区获取操作结果即可。

      
(4) 当需求控制对1个对象的造访,为不相同用户提供差别级其他走访权限时方可利用尊崇代理。

      
(5) 当须求为一个对象的访问(引用)提供一些非凡的操作时方可使用智能引用代理。

 

习题

       1.
Windows操作系统中的应用程序快速形式是(   
)形式的行使实例。

       A. 代理 (Proxy)            B. 组合 (Composite)

       C. 装饰 (Decorator)         D. 外观 (Facade)

       2.
结束学业生经过职业介绍所找工作,请问该进度包罗了哪一种设计情势,绘制相应的类图。

       3.
在某应用软件中须求记录业务方法的调用日志,在不改动现有业务类的根底上为每1个类提供七个日记记录代理类,在代理类中输出日志,如在工作方法Method()调用此前输出“方法Method()被调用,调用时间为二零一三-11-5
10:10:10”,调用之后若是没有抛极度则输出“方法Method()调用成功”,否则输出“方法Method()调用铩羽”。在代理类中调用真实业务类的事体方法,使用代理形式设计该日记记录模块的构造,绘制类图并使用C#言语编程模拟完结。

       4.
某软件商店欲开发一款基于C/S的网络图片查看器,具体效果描述如下:用户只需在图片查看器中输入网页U帕杰罗L,程序将自动将该网页全体图片下载到当地,考虑到多少网页图片比较多,而且一些图片文件比较大,由此将先以图标的点子浮现图片,差距品种的图片应用不一致的图标,并且在图标上面标注该图片的公文名,用户单击图标后可查阅真正的图样,界面效果如图15-7所示。试使用虚拟代理情势设计并促成该图片查看器。(注:可以组合二十四线程机制,使用二个线程突显小图标,同时开动另1个线程在后台加载原图。)【小编:刘伟(liú wěi )(Sunny)
 http://blog.csdn.net/lovelion

相关文章