1 代理模式定义
定义:给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过代理对象间接地操控原对象。
本篇文章主要介绍的是静态代理,关于动态代理请参考:设计模式之动态代理(dynamic proxy)
2 代理模式的作用
- 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
- 通过代理类对原有类进行功能增强,如增加缓存、异常处理、日志处理等,Spring AOP用的就是(动态)代理模式
3 代理模式一般涉及到的角色有:
- 抽象主题(Subject):声明真实对象和代理对象的共同接口;
- 代理(Proxy):代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
-
真实对象(RealSubject):代理角色所代表的真实对象,是我们最终要引用的对象。
4 应用场景举例:
下面我们就拿用户买火车票举一个例子,传统的火车票购买方式就是去火车站购买,除此之外,我们还可以通过火车票代售点或者12306网站购买,其实这里的火车票代售点就扮演着代理角色。下面我们通过代码演示一遍。
我们要购买火车票,就得有人卖票,我们定义一个卖票Subject。
public interface TicketSubject {
public void sell();
}
然后我们定义一个真实对象,传统的卖票的地方是火车站:
public class TrainStation implements TicketSubject {
public void sell() {
System.out.println("卖出一张票!");
}
}
最后再定义一个代理对象,火车站太远,我们想从代售点买票,定义一个代售点做代理类:
public class TrainStationProxy implements TicketSubject {
private TrainStation trainStation;//持有真实对象的引用
public TrainStationProxy(TrainStation trainStation){
this.trainStation=trainStation;
}
public void sell() {
System.out.println("欢迎光临!");
trainStation.sell();//调用真实对象的方法,体现代理行为
System.out.println("请交手续费!");
}
}
从代理类来看,它和真实对象实现的是同一个主题接口,并且内部还持有真实对象的引用,在自己的方法内调用真实对象的方法,完美的进行了代理,当然代理类可以在自己的方法里面添加一些额外的功能。
最后,我们测试一下
定义一个买票的人:
public class SomeBody {
private TicketSubject tickSubject;
public void buy(){
tickSubject.sell();
}
public void goToTicketSubject( TicketSubject tickSubject){
this.tickSubject=tickSubject;
}
}
注意,买票人依赖的是接口而不是具体实现类,这样就可以用代理类替换实际类了。
最后,这个人去代售点买票:
public class TestProxy {
public static void main(String[] args) {
SomeBody someBody=new SomeBody();
TrainStationProxy adaptor=new TrainStationProxy(new TrainStation());
someBody.goToTicketSubject(adaptor);
someBody.buy();
}
}
看一下打印结果:
欢迎光临!
卖出一张票!
请交手续费!
代理类完成了购票,还增加了收取手续费的功能!
本篇文章主要介绍的是静态代理,关于动态代理请参考:设计模式之动态代理(dynamic proxy)