一、概述
一般问题:在某些情况下,一个对象不适合或者不能直接引用另一个对象,比如对象创 建开销很大,或者某些操作需要安全控制,或者需要进程外的访问,或者直接访问会给使用者或者系统结构带来很多麻烦。
核心方案:为其他对象提供一种代理以控制对这个对象的访问。
设计意图:既然是代理,那么首先应该有两个对象:实现类和代理类。实现类是我们真正希望访问的,是功能的最终提供者,业务的最终完成者;代理类是介于访问者和实现类之间的中间层,代理类拥有实现类的实例,访问者通过访问代理类间接访问实现类。那么还有一个问题需要解决:代理类如何知道知道实现类能提供什么功能?一个最笨的方法就是为代理类添加实现类的同名方法,但是这样太难维护和扩展了。于是,我们需要一个规范接口,来定义代理类究竟代理实现类的哪些方法。然后让代理类和实现类同时实现该接口,以强制二者拥有代理功能的同名方法。换句话说,代理类中拥有的方法,必然对应实现类中的实现方法。
代理模式的最终设计结构如下:
二、应用场景
以向中介租房为例,设计一个代理模式:
IHouse接口定义如下:
public interface IHouse { String getAddress(); double getPrice(); }
HouseImpl实现类:
public class HouseImpl implements IHouse{ private String address; private double price; public HouseImpl(String address, double price){ this.address = address; this.price = price; } @Override public String getAddress() { return this.address; } @Override public double getPrice() { return this.price; } }
ProxyHouse代理类:
public class ProxyHouse implements IHouse{ private IHouse houseImpl; //被代理类 public ProxyHouse(IHouseImpl houseImpl){ this.houseImpl = houseImpl; } @Override public String getAddress() { return houseImpl.getAddress(); //由实际被代理类执行 } @Override public double signPrice() { if(houseImpl.getPrice() < 0){ //此处代表对接口做简单限制 return 0; } return houseImpl.getPrice(); } }
分析上面代码:
- HouseImpl和ProxyHouse都继承自IHouse抽象类,且重写了其声明的抽象方法。
- ProxyHouse是HouseImpl的代理类,其属性mHouseImpl即HouseImpl实例,在实现方法中直接调用mHouseImpl同名方法。
- HouseImpl是真正的实现者,是接口方法的具体执行者。
之所以这样设计,是方便对HouseImpl的方法做限制。
三、总结
优点:
- 职责清晰——代理类专注于提供代理方法,代码整洁,便于调用;
- 高扩展性——代理类可同时代理多个实现类,只要实现同一接口,拥有同名方法,而不必关心具体的实现。
缺点:
- 由于增加了代理层,可能使请求速度变慢;
- 由于添加了代理逻辑,增加了额外工作,可能使代码复杂化。
总结:
代理模式也叫委托模式,是一种结构型设计模式,当我们需要对某对象进行保护,或者对其访问进行控制,或者其他原因不便于直接访问时,应当考虑使用代理模式。尽管增加了额外的工作,但会让整体架构更加清晰、安全,易于维护和扩展。