Published on

设计模式(12)——代理 Proxy

Authors
  • avatar
    Name
    Leon
    Twitter

十二、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++实现:

  1. 编写一个类 ConcreteSubject 实现抽象基类 Subject, 基类有一个纯虚函数 Request()
  2. 编写一个代理类 Proxy, has-a 一个 Subject,通过 Proxy 的构造函数来初始化 Subject。
  3. 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;
}