引入
大家都知道,在十多年前,网络购票还没有普及的时候,我们长途出行都很麻烦,每次都得到火车站去买票。经常会排很长的队去买票,买了票得等好长时间才能坐上火车。那么如果我们想提前买票,怎么办呢?去火车站买了再跑回来?多麻烦!此时一个好东西解决了我们的困扰--车票代售点。有了它,我们可以就近就能买到火车票了,多方便。但值得注意的是,代售点买票是要收手续费的,不过我们就当花钱买个方便吧。仔细观察,我们可以发现,火车站售票具有售票的功能,代售点也有售票的功能,但代售点除了实现售票功能之外,还额外收取了手续费。其实这就是代理模式的一种实现。下面通过uml来简单表示它们之间的关系。
关系描述:
- 车站和代售点都有售票的功能,基于面向接口的编程原则,我们将售票功能提取为接口。代售点和车站都要实现它
- 代售点中持有对车站的引用。代售点出售的票是从车站来的,它售票核心的实现是通过车站来实现的。
- 代售点售票须收取手续费。车站售票是不需要手续费的,代售点售票收取手续费是对售票功能的增加,也称为增强
- 客户端直接通过代售点的售票功能来获得车站的票。
java代码实现
// 售票接口
public interface TicketService {
// 售票功能
void saleTicket();
}
// 车站类--目标类
public class Station implements TicketService{
@Override
public void saleTicket() {
System.out.println("售出车票:南充--成都,2020-04-08");
}
}
// 代售点--代理类
public class Agency implements TicketService{
private Station station;
public Agency(Station station) {
this.station = station;
}
@Override
public void saleTicket() {
// 通过车站售票
station.saleTicket();
//增强处理
System.out.println("收取¥5的手续费,美滋滋");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Agency agency = new Agency(new Station());
agency.saleTicket();
}
}
总结
- 代理类和目标类共同实现目标接口
- 代理类持有对目标对象的引用,可以调用目标对象的功能
- 客户端通过代理类来调用目标类的功能,并在调用前后进行增强处理
想一想
我们想要对一个类或接口进行代理,那么按照上面的模式,得为每一个类或接口生成一个代理类。假设我们的类和接口有足够多,都需要代理,怎么办?其实在实际的java项目中这种情况是很多的,比如我们要对项目中每个功能(接口)增加日志,那我们得为每个功能都得生成代理类,想想那得要写多少代理类啊?那么有没有什么好的方法呢?是有的,前面讲的其实是静态代理,代理还有一种灵动的模式--动态代理。这个东西真是很有用,功能之强大,用途之广泛,居家旅行必备。那么下一章,我们来说说动态代理。