代理模式
代理模式是对象结构型模式,主要是对对象的访问控制,处理对象的生命周期,也可以记录客户端的调用等。
在很多时候,我们使用的类的访问都是随意的,调用端可以随意调用我们的类,同时也无法检查有多少客户端真正使用这个类的对象。对于一些比较重的类,我们不是实时调用的化,无需立马创建。
这些问题,我们都可以使用代理模式进行很好的处理,代理模式就是对原有类的对象,进行访问控制,且可以对对象生命周期做调控,还可以记录日志和延时创建所需类。通过代理实现这些功能十分方便。
结构
说明
- 抽象主题(Subject)- 通过接口去定义真实主题(对象)所用的方法。
- 真实主题(Real Subject)- 实现具体业务方法,是整个代理模式的业务实现者。
- 代理(Proxy)- 提供和主题的所以方法,但实际调用的却是真实主题的方法。里面包含一个真实主题的引用,其作用在于控制调用端访问和对象生命周期。
实现
这里我们实现一个鼠标店
鼠标店接口 - 抽象主题
/// <summary>
/// <para>鼠标店接口(Subject)</para>
/// </summary>
public interface IMouseShop
{
//卖鼠标
void Sell();
}
鼠标店 - 具体主题
public class RealMouseShop : IMouseShop
{
public void Sell()
{
Debug.Log("卖出一个鼠标");
}
}
鼠标店代理 - 代理
public class MouseShopProxy : IMouseShop
{
private RealMouseShop _mouseShop;
private readonly int _maxShipment = 5;
private int _sellNumber;
public void Sell()
{
//延迟初始化
_mouseShop ??= new RealMouseShop();
//限制出口,俗称饥饿营销 0.0
if (_sellNumber >= _maxShipment)
{
Debug.Log("已经没有货了");
return;
}
_mouseShop.Sell();
_sellNumber++;
}
public void Stock()
{
Debug.Log("库存量为 : " + (_maxShipment - _sellNumber));
}
}
调用
public class ProxyExample : MonoBehaviour
{
private void Start()
{
MouseShopProxy proxy = new MouseShopProxy();
//查看库存
proxy.Stock();
for (int i = 0; i < 5; i++)
{
proxy.Sell();
}
proxy.Stock();
//看看是否继续卖出
proxy.Sell();
}
}
这个例子实现了代理模式的一些功能,包括控制访问,延时创建等,代理模式本身不直接实现业务逻辑,这点需要谨记。
应用场景
- 当我们需要去创建一些较重的对象时,可以使用延时创建,即虚拟代理
- 当我们需要控制客户端访问,查看访问数或限制访问数时,可以使用代理,即保护代理
- 对象在服务器端时,通过代理去访问,即远程代理
- 日志记录,访问记录
- 当需要缓存客户请求结果并对缓存生命周期进行管理时,可以使用代理,即缓存代理
- 在没有客户端使用某个重量级对象时立即销毁该对象。
利与弊
优点
- 控制客户端的访问和访问数
- 对对象生命周期的控制
- 在不修改对象代码的前提下,控制对象创建,访问等,符合开闭原则。
缺点
- 系统会变复杂
代理模式与其他模式的区别:适配器模式为对象提供变换后的接口,代理模式为对象提供相同接口,装饰模式为对象提供加强接口。
适配器在于转换接口,代理在于控制访问,装饰在于添加功能。
由于很多设计模式之间存在许多相似处,但本身的作用却大相径庭,需要细细甄别。
🐹🐹🐹