1.概念
代理模式是一种常见的设计模式,它允许你在不直接访问对象的情况下,通过一个代理对象来控制对该对象的访问。这个代理对象可以作为客户端和实际对象之间的中介,从而实现一些特定的控制功能,比如限制访问、记录访问日志等。
怎么理解呢,我们一般来说存在一个实际的对象,这个对象包含了丰富的业务方法,我们当然可以暴露出来给所有人使用。但是有时候我们并不希望这些方法没没有限制的使用,比如某个方法是重启服务器。如果这个方法不加约束的暴露给所有人,那将会是一场灾难。因此这个时候我们需要给这个对象一层保护壳,也就是代理,其它人都需要经过代理来访问它。再举一个例子。好比一个君主,如果随便让别人访问它,万一里面藏着刺客,这个君主随时面临生命危险。所以大家想要给君主传达信息,一般都是通过代理人(大臣)来帮忙传达,这就是代理模式的其中一种应用场景,安全代理。
2.组成结构
- 抽象主题(Subject):定义了代理和实际对象之间的共同接口。这个接口通常包含了代理对象需要实现的方法。
- 实际主题(Real Subject):定义了代理对象所代表的实际对象。
- 代理(Proxy):代理对象实现了抽象主题中的接口,并保存了对实际主题的引用。代理对象可以控制对实际对象的访问,比如限制访问或记录访问日志等。
3.示例代码
cpp
#pragma once
#include <string>
#include <iostream>
using namespace std;
//抽象类
class VideoSite
{
public:
virtual void freeMovie() = 0; //免费电影
virtual void vipMovie() = 0; //vip电影
virtual void ticketMovie() = 0;//用券电影
};
//具体实现类
class FixBugVideoSite : public VideoSite
{
public:
virtual void freeMovie() //免费电影
{
cout << "观看免费电影" << endl;
}
virtual void vipMovie() //vip电影
{
cout << "观看vip电影" << endl;
}
virtual void ticketMovie() //用券电影
{
cout << "用券观看电影" << endl;
}
};
//普通用户代理类
class FreeVideSiteProxy : public VideoSite
{
public:
FreeVideSiteProxy()
{
pVideo = new FixBugVideoSite();
}
~FreeVideSiteProxy()
{
delete pVideo;
}
virtual void freeMovie() //免费电影
{
pVideo->freeMovie(); //通过代理对象的freeMovie,来访问真正委托类对象的freeMovie方法
}
virtual void vipMovie() //vip电影
{
cout << "不好意思,您不是VIP,请先充值。" << endl;
}
virtual void ticketMovie()//用券电影
{
cout << "不好意思,您没有券,请先购买。" << endl;
}
private:
FixBugVideoSite* pVideo;
};
//VIP用户代理类
class vipVideSiteProxy : public VideoSite
{
public:
vipVideSiteProxy()
{
pVideo = new FixBugVideoSite();
}
~vipVideSiteProxy()
{
delete pVideo;
}
virtual void freeMovie() //免费电影
{
pVideo->freeMovie(); //通过代理对象的freeMovie,来访问真正委托类对象的freeMovie方法
}
virtual void vipMovie() //vip电影
{
pVideo->vipMovie();
}
virtual void ticketMovie()//用券电影
{
cout << "不好意思,您没有券,请先购买。" << endl;
}
private:
VideoSite* pVideo;
};
void main()
{
unique_ptr<VideoSite> p1(new FreeVideSiteProxy());
unique_ptr<VideoSite> p2(new vipVideSiteProxy());
p1->freeMovie();
p1->vipMovie();
p1->ticketMovie();
cout << "--------------------------" << endl;
p2->freeMovie();
p2->vipMovie();
p2->ticketMovie();
}
在上面的例子种,代理就是的作用就是做权限的隔绝。
4.应用场景
- 访问控制:代理模式可以用来控制对实际对象的访问权限。比如,只有特定用户或角色才能访问某些敏感数据。
- 远程访问:代理模式可以用来处理远程对象的访问。比如,通过代理对象来访问远程Web服务。
- 延迟加载:代理模式可以用来实现延迟加载。比如,通过代理对象来加载某些资源或数据,以避免在程序启动时就加载所有数据。
- 缓存:代理模式可以用来实现缓存。比如,代理对象可以缓存一些频繁访问的数据或结果,以提高程序的性能。
- 远程代理:当需要在不同的进程或机器之间进行通信时,可以使用远程代理来封装和管理通信的过程和数据。
- 虚拟代理:当需要延迟加载或预加载大量数据时,可以使用虚拟代理来提高程序的性能和效率。
- 安全代理:当需要限制外部对对象的访问权限时,可以使用安全代理来实现访问控制和管理。
- 缓存代理:当需要对经常使用的数据进行缓存时,可以使用缓存代理来管理和优化数据的访问效率。
- 智能指针代理:当需要对对象进行内存管理和安全释放时,可以使用智能指针代理来管理对象的生命周期。
5.优缺点
优点:
- 代理模式可以提供额外的访问控制,从而保证安全性。代理类可以拦截外部请求,并控制对实际对象的访问权限。
- 代理模式可以实现对实际对象的延迟加载。例如,在使用代理模式实现图片加载时,可以在实际需要加载图片时才创建实际对象,从而提高程序的性能和效率。
- 代理模式可以实现对实际对象的访问管理和优化。例如,在使用代理模式实现数据库连接时,可以通过代理类来管理连接池和连接的使用,从而优化数据库的访问效率。
- 代理模式可以实现对实际对象的增强和扩展。例如,在使用代理模式实现日志记录时,可以通过代理类来增强实际对象的功能,从而记录相关的日志信息。
缺点:
- 代理模式会增加程序的复杂度和开销。在代理模式中,需要创建额外的代理类,并对代理类和实际对象之间的接口和交互方式进行设计和实现。
- 代理模式可能会降低程序的性能和效率。在代理模式中,需要对代理类和实际对象之间的通信进行额外的开销和处理,从而可能会影响程序的性能和效率。