- Published on
设计模式(12)——代理 Proxy
- Authors
- Name
- Leon
十二、Proxy(代理模式,别名 Surrogate,对象结构型模式)
1. 意图:
为其他对象提供一种代理以控制对这个对象的访问。
2. 适用:
在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用 Proxy 模式。
2.1. 远程代理(Remote Proxy)
为一个对象在不同的地址空间提供局部代表。Coplien 称这种代理为“大使”(Ambassador)。为网络上的对象创建一个局部的本地代理,比如要操作一个对象(网络性能不好的时候,问题尤其突出),我们将这个操纵的过程交给一个代理去完成,Gof称之为远程代理(Remote Proxy);
2.2. 虚代理(Virtual Proxy)
根据需要创建开销很大的对象。比如显示一幅大的图片,我们将这个创建的过程交给代理去完成,Gof称之为虚代理(Virtual Proxy);
2.3. 保护代理(Protection Proxy)
控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。例如,在 Choices 操作系统中 KemelProxies 为操作系统对象提供了访问保护。如在 Jive 论坛中不同权限的用户(如管理员、普通用户等)将获得不同层次的操作权限,我们将这个工作交给一个代理去完成,GoF 称之为保护代理(Protection Proxy);
2.4. 智能指引(Smart Reference)
取代了简单的指针,它在访问对象进执行一些附加操作。它的典型用途包括:
- 对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它(也称为 Smart Pointers )。
- 当第一次引用一个持久对象时,将它装入内存。
- 在访问一个实际对象前,橙果是否已经锁定了它,以确保其他对象不能改变它。
3. 类图:
4. Proxy 与 Adapter
Proxy 提供的接口(方法、函数)与实体同名,是一致的,而 Adapter 与 Adaptee 的接口(方法、函数)名称可能不同。适配器模式与代理模式最大的不同还是在于他们的出发点(初心)不同,适配器模式是为了做兼容,而代理模式的核心是为了增加功能。当然适配器在做适配的时候,也可以增加功能,这样它就跟代理模式非常接近了。
5. 中间层思考:
在系统与访问实体之间添加了一个代理,这个代理就是中间层。代理提供了和访问实体一样的接口,系统在不用改变调用方式的情况下,可以增强访问实体的功能,对访问实体添加保护功能等。
6. C++实现:
- 编写一个类
ConcreteSubject
实现抽象基类Subject
, 基类有一个纯虚函数Request()
- 编写一个代理类
Proxy
,has-a
一个Subject
,通过 Proxy 的构造函数来初始化 Subject。 - 在
Proxy
类中编写同名函数Request()
,其中添加一些附加的功能,然后调用Subject
的函数Request()
Proxy.h
//Proxy.h
#pragma once
class Subject {
public:
virtual ~Subject();
virtual void Request() = 0;
protected:
Subject();
private:
};
class ConcreteSubject : public Subject {
public:
ConcreteSubject();
~ConcreteSubject();
void Request();
protected:
private:
};
class Proxy {
public:
Proxy();
Proxy(Subject* sub);
~Proxy();
void Request();
protected:
private:
Subject* _sub;
};
Proxy.cpp
//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() {}
Proxy::Proxy(Subject* sub) {
_sub = sub;
}
Proxy::~Proxy() {
delete _sub;
}
void Proxy::Request() {
cout << "Proxy request...." << endl;
_sub->Request();
}
main.cpp
//main.cpp
#include "Proxy.h"
#include <iostream>
using namespace::std;
int main(int argc, char* argv[]) {
Subject* sub = new ConcreteSubject();
Proxy* p = new Proxy(sub);
p->Request();
return 0;
}