代理模式-C++实现
代理模式是一种结构型设计模式,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者无法引用另一个对象,这个时候就需要一个代理对象充当客户端和目标对象之间的中介。
代理模式就是代理对象具备目标对象的所有功能,并代替真实对象完成相应操作,在操作前或操作后进行功能增强的工作。这也是代理对象和目标对象之间的区别。
举例:
以租房为例,租客想要租房,需要经过房屋中介审核租客资料,审核通过之后才可以通知房东进行租房。
// 抽象房东类
class Landlord
{
public:
virtual ~Landlord() {}
virtual void Rent() = 0;
};
// 具体房东类
class RealLandlord
: public Landlord
{
public:
virtual void Rent() override
{
std::cout << "房东出租房屋" << std::endl;
}
};
// 中介代理
class EstateAgent
: public Landlord
{
public:
EstateAgent(){}
virtual void Rent() override
{
if (CheckTenant())
{
std::cout << "中介已代理,接受租客请求" << std::endl;
if (!landLord_)
landLord_ = std::make_shared<RealLandlord>();
landLord_->Rent();
std::cout << "中介代理,签订租约" << std::endl;
}
else
std::cout << "抱歉,您的资质审核未通过" << std::endl;
}
private:
bool CheckTenant()
{
// 检查租客资质
// ....
return true; // 假设检查成功
}
private:
std::shared_ptr<Landlord> landLord_;
};
测试:
void TestProxy()
{
std::shared_ptr<Landlord> agent = std::make_shared<EstateAgent>();
agent->Rent();
}
我们创建一个抽象房东类Landlord,定义了一个出租房屋的方法,一个真实目标对象去实现这个方法。还创建了一个中介代理类EstateAgent代替真实目标对象完成功能。
在中介代理类中,我们可以在出租房屋前后进行一些增强操作,比如检查租客资质等。
客户端方面,我们只需要创建一个代理对象,它会代替真实对象完成功能,客户端就不需要关心真实对象的创建逻辑。
代理模式遵循的设计原则:
1、单一职责原则:代理模式在客户端和实际对象之间额外增加了一个代理对象,使得代理对象具有更多的责任,而实际对象只需要专注自己的职责即可。
2、开放封闭原则:由于代理模式增加了代理类这一角色,所以可以在不修改现有代码的情况下添加新的代理类达到添加新功能的需求。比如上述例子我们可以添加一个新的代理类,这个代理类的职责是只检查房东资质。该模式使得对实际对象的访问和控制可以在代理层进行变化和扩展。
3、依赖倒置原则:代理模式通过引入抽象的代理接口,将客户端从实际对象解耦,客户端只需要面向代理接口编程,不需要直接依赖实际对象的具体实现。
优点:
1、隐藏对象复杂性:代理对象封装了实际对象的复杂性,使得客户端对实际对象的操作变得简单
2、提供额外的功能:代理对象可以在实际对象的基础上添加额外的功能,比如日志记录、权限验证、缓存等。
3、提供性能:代理模式允许延迟加载对象(在使用的时候才加载对象),从而避免了资源消耗和提高性能。
4、保护实际对象:代理对象将实际对象的功能封装起来,客户端就不能对实际对象直接访问
5、提供远程访问能力:通过代理模式,客户端可以访问远程对象,比如从而实现分布式系统或系统调用。
缺点:
1、会增加代码复杂性:代理模式增加了代理类作为客户端和实际对象之间的中间层。
2、可能引起性能损失:在某些情况下,代理模式可能会引入额外的开销,导致性能略有下降。
为什么会引起性能损失:
1、远程代理:当使用远程代理时,由于需要通过网络传输数据,可能会引起性能下降。因此,应该尽量减少网络通信量,使用缓存或其他优化技术。
2、虚拟代理:当使用虚拟代理时,由于需要创建和初始化代理对象,可能会引起一定的性能下降。因此,应该尽量减少代理对象创建的时间和开销。
3、安全代理:当使用安全代理时,由于需要进行权限验证和访问控制,可能会引起一定的性能下降。因此,应该尽量采用高效的算法和数据结构,减少耗时的操作。
4、智能引用代理:当使用智能引用代理时,由于需要记录对象的使用情况和状态,可能会引起一定的性能下降。因此,应该尽量减少对代理对象的状态记录和操作。
5、延迟加载代理:当使用延迟加载代理时,由于需要推迟实际对象的创建或加载,可能会引起一定的性能下降。因此,应该尽量减少延迟加载的时间和开销,避免对用户体验造成影响。