🔍目的
为另一个对象提供代理或占位符以控制对其的访问。
🔍解释
真实世界例子
想象有一个塔,当地的巫师去那里学习他们的法术。象牙塔只能够通过代理来进入以此来保证只有首先3个巫师才能进入。这里的代理就代表的塔的功能并添加访问控制。
通俗描述
使用代理模式,一个类代表另一个类的功能。
维基百科
在最一般的形式上,代理是一个类,它充当与其他对象的接口。代理是客户端调用的包装器或代理对象,以访问后台的实际服务对象。代理本身可以简单地转发到真实对象,也可以提供其他逻辑。在代理中,可以提供额外的功能,例如在对实对象的操作占用大量资源时进行缓存,或者在对实对象的操作被调用之前检查前提条件。
程序示例
上面的巫师塔为例。首先我们有巫师塔接口和象牙塔类 :
public interface WizardTower {void enter(Wizard wizard);
}public class IvoryTower implements WizardTower {private static final Logger LOGGER = LoggerFactory.getLogger(IvoryTower.class);public void enter(Wizard wizard) {LOGGER.info("{} enters the tower.", wizard);}}
创建一个简单的巫师类。
public class Wizard {private final String name;public Wizard(String name) {this.name = name;}@Overridepublic String toString() {return name;}
}
然后我们有巫师塔代理类为巫师塔添加访问控制
public class WizardTowerProxy implements WizardTower {private static final Logger LOGGER = LoggerFactory.getLogger(WizardTowerProxy.class);private static final int NUM_WIZARDS_ALLOWED = 3;private int numWizards;private final WizardTower tower;public WizardTowerProxy(WizardTower tower) {this.tower = tower;}@Overridepublic void enter(Wizard wizard) {if (numWizards < NUM_WIZARDS_ALLOWED) {tower.enter(wizard);numWizards++;} else {LOGGER.info("{} is not allowed to enter!", wizard);}}
}
然后这是进入塔的场景
var proxy = new WizardTowerProxy(new IvoryTower());
proxy.enter(new Wizard("Red wizard"));
proxy.enter(new Wizard("White wizard"));
proxy.enter(new Wizard("Black wizard"));
proxy.enter(new Wizard("Green wizard"));
proxy.enter(new Wizard("Brown wizard"));
程序输出:
Red wizard enters the tower.
White wizard enters the tower.
Black wizard enters the tower.
Green wizard is not allowed to enter!
Brown wizard is not allowed to enter!
🔍类图
🔍适用场景
代理适用于需要比简单指针更广泛或更复杂的对象引用的情况。这是代理模式适用的几种常见情况。
- 远程代理为不同地址空间中的对象提供了本地代表。
- 虚拟代理根据需要创建昂贵的对象。
- 保护代理控制对原始对象的访问。当对象有不同的接入权限时保护代理很有用。
🔍Ending
代理对象通常具有与实际对象相同的接口,使得客户端可以无需知晓实际对象的存在就能与代理对象进行交互。代理对象可以在客户端与实际对象之间添加额外的逻辑,比如对实际对象的访问进行控制、缓存对象的数据、延迟实际对象的创建等。
希望本文能够帮助读者更深入地理解代理模式,在实际项目中发挥其优势。谢谢阅读!
希望这份博客草稿能够帮助到你。如果有其他需要修改或添加的地方,请随时告诉我。