代理模式属于结构型模式。
代理模式中,一个类代表另一个类的功能。
我们需要创建现有对象的对象,用于对外提供功能接口。
为什么要创建现有对象的对象?
为了限制对某些对象进行访问控制。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
以租房为例,目前有这样一种中介公司,他们会把房东手中的房源装修成公寓,而公司全权负责对公寓的租赁、管理和维护。租户虽然租的是房东的房屋,但是不会跟房东发生直接的交流。这就是生活中的代理模式。假设我们就是要租一间这样的公寓。
1、先实现一个租房接口类IRentHouse,定义了租房这个服务
class IRentHouse
{
public:
virtual void rentHouse() = 0;
};
2、房东手中的房源RentHouse 需要继承IRentHouse接口
class Landlord : public IRentHouse
{
public:
virtual void rentHouse()
{
cout << "租了一间房" << endl;
}
};
3、定义一个代理类,也继承接口IRentHouse,实现对房东的租房控制和管理。代理类需要获取目标对象的指针
class IntermediaryProxy : public IRentHouse
{
public:
IntermediaryProxy(IRentHouse* iRentHouse):
_rentHouse(iRentHouse) {}
~IntermediaryProxy()
{
if(nullptr != _rentHouse)
{
delete _rentHouse;
_rentHouse = nullptr;
}
}
virtual void rentHouse()
{
//首先找到中介,交中介费用
PayIntermediaryFee();
//中介代理房东租房给客户
if (nullptr != _rentHouse)
{
_rentHouse->rentHouse();
}
//中介对房屋进行管理和维修
ManagerAndMaintain();
}
private:
void PayIntermediaryFee()
{
cout << "交中介费" << endl;
}
void ManagerAndMaintain()
{
cout << "管理和维护房屋" << endl;
}
private:
IRentHouse* _rentHouse;
};
4、通过中介租房
int main()
{
IRentHouse* landlord = new Landlord();
IRentHouse* rentHouseProxy = new IntermediaryProxy(landlord);
//通过中介租房
rentHouseProxy->rentHouse();
delete rentHouseProxy;
delete landlord;
system("pause");
return 0;
}
从静态代理的实现可以看到,只要我们能够获取到“房东”的对象指针,我们还是可以直接从房东租房的。如果我们需要避免用户直接从房东租到房间,可以使用强制代理的方式。
1、接口类增加GetProxy的声明,GetProxy函数是通过“房东”指针获取代理的方法
class IRentHouse
{
public:
virtual void rentHouse() = 0;
virtual IRentHouse* GetProxy() = 0;
virtual ~IRentHouse() {}
};
2、代理类修改:增加接口类中新函数GetProxy的实现
class IntermediaryProxy : public IRentHouse
{
public:
IntermediaryProxy(IRentHouse* iRentHouse) :
_rentHouse(iRentHouse) {}
virtual ~IntermediaryProxy()
{
if (nullptr != _rentHouse)
{
delete _rentHouse;
_rentHouse = nullptr;
}
}
virtual void rentHouse()
{
PayInterFee();
//中介代理房东租房给客户
if (nullptr != _rentHouse)
{
_rentHouse->rentHouse();
}
//中介对房屋进行管理和维修
ManagerAndMaintain();
}
virtual IRentHouse* GetProxy()
{
return this;
}
private:
void PayInterFee()
{
cout << "交中介费" << endl;
}
void ManagerAndMaintain()
{
cout << "中介管理和维护房屋" << endl;
}
private:
IRentHouse* _rentHouse;
};
3、房东类修改:1)增加获取代理的方式GetProxy;2、修改rentHouse逻辑,使其无法通过房东指针直接租到房间
class Landlord : public IRentHouse
{
public:
Landlord() : _proxy(nullptr) {}
virtual ~Landlord()
{
if (nullptr != _proxy)
{
delete _proxy;
_proxy = nullptr;
}
}
virtual void rentHouse()
{
if (IsProxy())
{
cout << "租了一间房" << endl;
}
else
{
cout << "请找中介" << endl;
}
}
virtual IRentHouse* GetProxy()
{
if (nullptr == _proxy)
{
_proxy = new IntermediaryProxy(this);
}
return _proxy;
}
private:
bool IsProxy()
{
//不是中介
if (nullptr == _proxy)
{
return false;
}
return true;
}
private:
IRentHouse* _proxy;
};
4、调用房东租房(失败),通过房东获取到的代理租房(成功)
int main()
{
//直接找房东
IRentHouse* landlord = new Landlord();
landlord->rentHouse(); //会返回"请找中介"
landlord->GetProxy()->rentHouse(); //可以租房
system("pause");
return 0;
}
【参考&致谢】
https://zhuanlan.zhihu.com/p/72644638https://zhuanlan.zhihu.com/p/72644638