代理模式: 为其他对象提供一种代理,并以控制对这个对象的访问。(Provide a surrogate or placeholder for another object to control access to it. )
而对一个对象进行访问控制的一个原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。
它是给某一个对象提供一个替代者(占位者),使之在client对象和subject对象之间编码更有效率。
代理可以提供延迟实例化(lazy instantiation),控制访问, 等等,包括只在调用中传递。
一个处理纯本地资源的代理有时被称作虚拟代理;远程服务的代理常常称为远程代理;强制控制访问的代理称为保护代理
代理模式中的三种角色
(1)抽象角色(ICar):声明真实对象和代理对象的共同接口。
(2)代理角色(ProxyCar):代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,
同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。
同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
(3)真实角色(Car):代理角色所代表的真实对象,是我们最终要引用的对象。
实用性
在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用 Proxy模式。下面是一些可以使用Proxy模式常见情况:
(1) 远程代理(Remote Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。
这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又叫做大使(Ambassador)
(2) 虚拟代理(Virtual Proxy)根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,
真实对象只在需要时才会被真正创建。
(3) 保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
(4) 智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。
(5) Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。
一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆
Proxy.h
#ifndef _PROXY_H_
#define _PROXY_H_
#include <iostream>
using std::cout;
using std::endl;
class Driver
{
public:
Driver(int);
int getAge();
void setAge(int);
public:
int age_;
};
class ICar
{
public:
virtual void MoveCar() = 0;
};
class Car : public ICar
{
virtual void MoveCar();
};
//the proxy car
class ProxyCar
{
public:
ProxyCar(Driver *, ICar *);
void MoveCar();
private:
Driver * driver_;
ICar * car_;
};
#endif
Proxy.cpp
#include "Proxy.h"
Driver::Driver(int age) : age_(age)
{
}
void Driver::setAge(int age)
{
age_ = age;
}
int Driver::getAge()
{
return age_;
}
void Car::MoveCar()
{
cout << "Car has been driven" << endl;
}
ProxyCar::ProxyCar(Driver * d, ICar *c)
{
driver_ = d;
car_ = c;
}
void ProxyCar::MoveCar()
{
if (driver_->age_ <= 16)
cout << "Sorry the driver is too young to drive" << endl;
else
car_->MoveCar();
}
main.cpp
#include "Proxy.h"
int main()
{
Driver d1(16);
Car car;
ProxyCar p1(&d1, &car);
p1.MoveCar();
Driver d2(20);
ProxyCar p2(&d2, &car);
p2.MoveCar();
return 0;
}
Makefile
cc=g++
exe=main
obj= main.o Proxy.o
$(exe): $(obj)
$(cc) -g -o $(exe) $(obj)
main.o: main.cpp Proxy.h
$(cc) -g -c main.cpp
Proxy.o: Proxy.cpp Proxy.h
$(cc) -g -c Proxy.cpp
clean:
rm -rf *o $(exe)