概念
Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问。
所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。
类图角色和职责
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
代理模式中的角色如下:
-
抽象主题角色(Subject):可以是抽象类,也可以是接口。定义真实主题角色RealSubject 和 抽象主题角色Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。
-
具体主题角色(RealSubject):也叫做被委托角色或被代理角色,是业务逻辑的具体执行者。定义了代理角色(proxy)所代表的具体对象
-
代理主题角色(Proxy):也叫做委托类或代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在具体主题角色处理完毕前后做预处理和善后处理工作。
适合于:
为其他对象提供一种代理以控制对这个对象的访问。
提示:a中包含b类;a、b类实现协议类protocol
#include <iostream>
using namespace std;
/*
结构型模式: 让类和类组合,获取更大的结构
重要的有 代理模式、装饰模式、适配器模式、 桥接模式
Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象
提供一种代理(Proxy)以控制对这个对象的访问。
所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端
必须通过代理与被代理的目标类 交互,而代理一般在交互的过程中(交互前后),
进行某些特别的处理。
代理类可以在真正的类执行之前,进行预处理
实现了业务和核心功能分离,彻底解耦
*/
//抽象类
class Subject
{
public:
virtual void sailbook() = 0;
};
class RealSubjectBook : Subject
{
public:
virtual void sailbook()
{
cout << "实体店卖书" << endl;
}
};
//a中包含b类;a、b类实现协议类protocol
//代理 也继承抽象类
class dangdangProxy : public Subject
{
public:
virtual void sailbook()
{
m_rsb = new RealSubjectBook;
//调用之前,不仅帮着卖书,还可以做扩一些功能
dazhe();
m_rsb->sailbook();
//调用之后,不仅帮着卖书,还可以做扩一些功能
dazhe();
delete m_rsb;
}
public:
void dazhe()
{
cout << "双十一打折" << endl;
}
private:
RealSubjectBook *m_rsb;
};
void test01()
{
Subject *s = new dangdangProxy;
s->sailbook();
delete s;
}
///
//假若你有一个工厂开始是生产手机的,但是它现在不想自己生产了,它把自己的东西
//交给了一家代工厂富士康去生产,那么便有了下面的代码去构建。
//统一抽象接口 IFactory
class IFactory
{
public:
virtual void makeProduct() = 0;
//virtual ~IFactory(){};
};
//你的手机工厂
class PhoneFactory : public IFactory
{
public:
~PhoneFactory()
{
cout << "~PhoneFactory()" << endl;
}
virtual void makeProduct()
{
cout << "生产手机" << endl;
}
};
//专门做代工的代理工厂富士康
class FoxconnProxy : public IFactory
{
public:
FoxconnProxy(IFactory * factory)
{
m_real = factory;
}
~FoxconnProxy()
{
cout << "~FoxconnProxy()" << endl;
}
virtual void makeProduct()
{
checkBefore();
m_real->makeProduct();
checkAfter();
}
void checkBefore()
{
cout << "检查零件是否合格" << endl;
}
void checkAfter()
{
cout << "检查手机是否包装完好" << endl;
}
private:
IFactory *m_real;//基类
};
void test02()
{
IFactory *factory = new PhoneFactory;//多态
FoxconnProxy *proxy = new FoxconnProxy(factory);
proxy->makeProduct();
delete factory;//多态 必须用虚析构才可以
delete proxy;
}
int main()
{
cout << "---------------例子1----------------" << endl;
test01();
cout << "---------------例子2----------------" << endl;
test02();
cout << "hello...." << endl;
system("pause");
return 0;
}
/*
虚析构函数应用场景:通过父类指针释放所有的子类对象
1、 c++中不能声明虚构造函数。派生类对象撤销时,先调用派生类的析构,然后
再调用基类的析构。
delete无名对象时候,只执行基类的析构函数,而不执行派生类的析构函数。
原因是调用析构函数时,采用了静态联编方式,只调用了基类的析构函数。
3、 基类的析构函数加上virtual,虽然派生类和基类的析构函数名字不同,但由
该基类所派生的所有派生类的析构函数也都自动成为虚函数。
4、 虚析构函数采用了动态联编,实现了运行时的多态。
*/
总结
优点:
1.职责清晰。2.高扩展性。3.智能化。
缺点:
1.由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。2.实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
对比
代理模式与外观模式:
1.代理模式中的代理角色和真实角色都继承于同一类。而外观模式是多个类的集合。
2.代理角色与真实角色接口相同,功能一致,代理角色实现的是真实角色的功能。外观者模式的子系统功能不同,根据用户不同需要与外观类统一配置。
3.实现方式上,外观模式是产生一个新类,封装内部操作;代理是产生一个继承类,操作对用户看起来是一样的。
代理模式与适配器模式
适配器模式主要改变所考虑对象的接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作,大多用在代码维护的后期,或者借用第三方库的情况下;而代理模式不能改变所代理类的接口。
代理模式与装饰模式
装饰器模式为了增强功能,而代理模式是为了加以控制。(该部分区别在装饰模式有所阐述)
代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是通过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务
适用场景
根据目的和实现方式的不同,代理模式可分为很多种,常见的有:
远程代理(Remote Proxy)
为一个位于不同地址空间的对象提供一个本地代理,对代理的方法调用会导致对远程对象的方法调用。ATM 就是一个例子,ATM 可能会持有(存在于远程服务器中的)银行信息的一个代理对象。
虚拟代理(Virtual Proxy)
使用虚拟代理,代理可以作为一个(资源消耗较大的)对象的代表。虚拟代理经常延迟对象的创建,直到需要为止。在创建对象之前(及创建对象过程中),虚拟代理也可以作为对象的代理;之后,代理将请求直接委托给 RealSubject。
保护代理(Protection Proxy)
根据访问权限,可以使用保护代理来控制对资源的访问。例如,有一个员工对象,保护代理可以允许普通员工调用对象的某些方法,管理员调用其他方法。
缓冲代理(Cache Proxy)
为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
智能引用代理(Smart Reference Proxy)
当一个对象被引用时,提供一些额外的操作(例如:将对象被调用的次数记录下来)。