Proxy模式详解--设计模式(11)

Proxy模式的产生原因:

       在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

当由于某些特定的需要调用的对象在另外一台机器上,需要跨越网络才能访问,在没有WebService的情况下我们需要直接coding去处理网络连接、处理打包、解包等等非常复杂的步骤,而WebService的出现帮我们解决了其中的一些问题简化客户端的处理,我们只需在客户端建立一个远程对象的代理,客户端就象调用本地对象一样调用该代理,再由代理去跟实际对象联系,对于客户端来说可能根本没有感觉到调用的东西在网络另外一端。

Proxy模式的作用:

提供一个Subject角色,它定义了Proxy与ConcreteSubject的功用接口,使得任何使用ConcreteSubject的地方都能使用Proxy,Proxy对象维护了一个对ConcreteSubject对象的引用,Proxy接受来至客户端请求,通过这个引用,将请求转给具体的ConcreteSubject对象,Proxy在执行具体对象操作时可以附加其他的操作。这样通过增加代理来解耦客户端与调用对象之间的调用,封装了原来客户端调用具体对象的一些相关细节,客户端不在依赖具体的调用对象,具体对象的修改对客户端来说是透明的,不会影响客户端的修改。

Proxy模式的构成:

抽象主题(Subject)角色:声明了代理主题和具体主题的公共接口,使任何需要具体主题的地方都能用代理主题代替。

代理主题(Proxy)角色:代理对象角色内部含有对具体对象的引用,从而可以操作具体对象,同时代理对象提供与具体对象相同的接口以便在任何时刻都能代替具体对象。同时,代理对象可以在执行具体对象操作时,附加其他的操作,相当于对具体对象进行封装。

具体具体对象(ConcreteSubject)角色:代理角色所代表的具体对象,是我们最终要引用的对象。

Proxy模式典型的结构图如图1所示:

               

Proxy模式的示例程序:

Proxy.h

#ifndef _PROXY_H_
#define _PROXY_H_

// 定义了Proxy和ConcreteSubject的公有接口,
// 这样就可以在任何需要使用到ConcreteSubject的地方都使用Proxy.
class Subject
{
public:
    virtual ~Subject();
    virtual void Request()=0;
protected:
    Subject();
};

class ConcreteSubject : public Subject
{
public:
    ConcreteSubject();
    ~ConcreteSubject();
    virtual void Request();
};

//定义代理类
class Proxy : public Subject
{
public:
    Proxy();
    ~Proxy();
    void DoSomething1();
    virtual void Request();
    void DoSomething2();
private:
    Subject* _subject;
};
#endif

Proxy.cpp

#include "Proxy.h"
#include "iostream"

using namespace std;

Subject::Subject()
{}

Subject::~Subject()
{}

ConcreteSubject::ConcreteSubject()
{}

ConcreteSubject::~ConcreteSubject()
{}

void ConcreteSubject::Request()
{
    cout << "ConcreteSubject::Request" << endl;
}

Proxy::Proxy() : _subject(NULL)
{}

Proxy::~Proxy()
{}

void Proxy::DoSomething1()
{
    cout << "Proxy::DoSomething1" << endl;
}

void Proxy::DoSomething2()
{
    cout << "Proxy::DoSomething2" << endl;
}

void Proxy::Request()
{
    if(NULL == this->_subject)
    {
        this->_subject = new ConcreteSubject();
    }

    this->DoSomething1();//表示额外附加的操作

    this->_subject->Request();//代理的实体类操作

    this->DoSomething2();//表示额外附加的操作
}

Main.cpp

#include "Proxy.h"

int main()
{
    Proxy* proxy = new Proxy();
    proxy->Request();

    return 0;
}

Proxy模式使用场景:

(1).创建开销大的对象时候,比如显示一幅大的图片,我们将这个创建的过程交给代理去完成,GoF称之为虚代理(Virtual Proxy)。

(2).为网络上的对象创建一个局部的本地代理,比如要操作一个网络上的一个对象(网络性能不好的时候,问题尤其突出),我们将这个操纵的过程交给一个代理去完成,GoF称之为远程代理(Remote Proxy)。

(3).对对象进行控制访问的时候,比如在Jive论坛中不同权限的用户(如管理员、普通用户等)将获得不同层次的操作权限,我们将这个工作交给一个代理去完成,GoF称之为保护代理(Protection Proxy)。

(4).当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。是指当调用真实的对象时,代理处理另外一些事。如计算真实对象的引用次数,这样当该对象没有引用时,可以自动释放它;或当第一次引用一个持久对象时,将它装入内存;或在访问一个实际对象前,检查是否已经锁定它,以确保其他对象不能改变它。它们都是通过代理在访问一个对象时附加一些内务处理。又称智能引用(Smart Reference)代理。

在所有种类的代理模式中,虚拟(Virtual)代理、远程(Remote)代理、智能引用代理(Smart Reference Proxy)和保护(Protect or Access)代理是最为常见的代理模式。

Proxy代理模式与外观模式的区别:

(1).外观模式也是屏蔽复杂性的,但是外观模式不会实现客户端调用的目标类型接口。

(2).一般客户端调用外观模式的方法都是直接调用。

(3).代理模式中对客户端目标对象类型抽象接口具体化了。

(4).外观模式是代理模式中一种特殊的子级模式(广泛的,非约束性)。

Proxy代理模式使用总结:

Proxy代理模式非常常用,大致的思想就是通过为对象加一个代理来降低对象的使用复杂度、或是提升对象使用的友好度、或是提高对象使用的效率。

GoF《设计模式》中说的:为其他对象提供一种代理以控制这个对象的访问。理类型从某种角度上讲也可以起到控制被代理类型的访问的作用。

时间: 2024-10-12 22:47:51

Proxy模式详解--设计模式(11)的相关文章

Interpreter 模式详解--设计模式(22)

Interpreter 模式的来源: Interpreter(解释器)模式是一种特殊的设计模式,它建立一个解释器(Interpreter),对于特定的计算机程序设计语言,用来解释预先定义的文法.简单地说,Interpreter模式是一种简单的语法解释器构架.解释器模式属于行为模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. Interpreter 模式作用:     正如其名,此模式大多用来解释一些(自定义的)独特语法,例如某些游戏开发引擎中

Observer模式详解--设计模式(15)

Observer模式来源: Observer模式应该可以说是应用最多.影响最广的模式之一. 因为Observer的一个实例Model/View/Control(MVC)结构在系统开发架构设计中有着很重要的地位和意义,MVC实现了业务逻辑和表示层的解耦.在MFC中,Doc/View(文档视图结构)提供了实现MVC的框架结构(有一个从设计模式(Observer模式)的角度分析分析Doc/View的文章正在进一步的撰写当中,遗憾的是时间:)).在Java阵容中,Struts则提供和MFC中Doc/Vi

Strategy模式详解--设计模式(13)

Strategy模式来源:        在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查找.排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法:当然也可以将这些查找算法封装在一个统一的方法中,通过if-else-或者case等条件判断语句来进行选择.这两种实现方法我们都可以称之为硬编

Facade模式详解--设计模式(10)

Facade模式产生原因: 老旧的code(尤其是将C的代码转成C++代码)或者即便不是老旧code,但涉及多个子系统时,除了重写全部代码(对于老旧code而言),我们还可能采用这样一种策略:重新进行类的设计,将原来分散在源码中的类/结构及方法重新组合,形成新的.统一的接口,供上层应用使用.这在某种意义上与Adapter及Proxy有类似之处,但是,Proxy(代理)注重在为Client-Subject提供一个访问的中间层,如CORBA可为应用程序提供透明访问支持,使应用程序无需去考虑平台及网络

C++Builder建造者模式详解--设计模式(4)

生活中有着很多的Builder的例子,个人觉得大学生活就是一个Builder模式的最好体验:要完成大学教育,一般将大学教育过程分成4个学期进行,因此没有学习可以看作是构建完整大学教育的一个部分构建过程,每个人经过这4年的(4个阶段)构建过程得到的最后的结果不一样,因为可能在四个阶段的构建中引入了很多的参数(每个人的机会和际遇不完全相同). Builder模式要解决的也正是这样的问题:当我们要创建的对象很复杂的时候(通常是由很多其他的对象组合而成),我们要要复杂对象的创建过程和这个对象的表示(展示

Memento模式详解--设计模式(16)

Memento模式来源:      我们在进行软件系统的设计时候是要给用户后悔的权利(实际上可能也是用户要求的权利:)),我们对一些关键性的操作肯定需要提供诸如撤销(Undo)的操作.那这个后悔药就是Memento模式提供的. Memento模式作用:       在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态. Memento模式UML结构图如图1所示:                       Memento模式构成:

Template模式详解--设计模式(12)

Template模式来源:    在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,但是逻辑(算法)的框架(或通用的应用算法)是相同的.Template提供了这种情况的一个实现框架. Template模式作用: Template模式又叫模板方法模式,在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情冴下,重新定义算法中的某些步骤. 我们使用冲泡咖啡和冲泡茶的例子 加工流程: 咖啡冲

State模式详解--设计模式(14)

State模式来源:         每个人.事物在不同的状态下会有不同表现(动作),而一个状态又会在不同的表现下转移到下一个不同的状态(State).最简单的一个生活中的例子就是:地铁入口处,如果你放入正确的地铁票,门就会打开让你通过.在出口处也是验票,如果正确你就可以ok,否则就不让你通过(如果你动作野蛮,或许会有报警(Alarm)). 有限状态自动机(FSM)也是一个典型的状态不同,对输入有不同的响应(状态转移).通常我们在实现这类系统会使用到很多的Switch/Case语句,Case某种

Iterator模式详解--设计模式(21)

Iterator模式来源: 迭代器(Iterator)模式,又叫做游标(Cursor)模式.GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节.从定义可见,迭代器模式是为容器而生. Iterator模式作用: (1).它支持以不同的方式遍历一个聚合复杂的聚合可用多种方式进行遍历,如二叉树的遍历,可以采用前序.中序或后序遍历.迭代器模式使得改变遍历算法变得很容易: 仅需用一个不同的迭代器的实例代替原先的实例即可,你也可以自己定义迭代器的子