大家好,上一篇博客讲到了装饰器模式,而这一篇,我们要讲到代理模式。这篇代理模式酝酿了好久。为什么呢?因为我在写这些模式系列的博客中,都会先阅读网上的介绍这些模式的博客,看看别人是怎么写的,有什么问题别人是还没有解释清楚的,有什么我是可以补充并且增加的,或者换一种介绍的方式。从而写出具有自己特色的,有价值的博客。
有一些代理模式的文章举的例子很像装饰器模式,所以很多人会在评论下面留言说,楼主写的不就是装饰器模式吗?并不是代理模式吧,怀着这个疑问,我看了很多文章,好像找到一点感觉,但是又好像不够确定。于是我想起来之前看过的一本书《大话设计模式》,终于在这个书里面确定了自己的思路。
首先,代理模式是有静态代理模式和动态代理模式之分的。网上的大部分争议来自于静态代理模式。很多人说其他博主举的例子是装饰模式,不是代理模式。那倒是是装饰还是代理呢?我们先来拿买火车票来举例子吧,因为现实中,不少人是得靠黄牛刷票才买的到过年回家的票的。手动笑哭~
先写一个买票的接口吧。
public interface IBuyTicket {
void buyTicket();
}
然后我们写一个实现类:
public class BuyTicket implements IBuyTicket {
@Override
public void buyTicket() {
System.out.println("买过年回家的票");
}
}
然后关键就到了我们的代理类怎么写了:
public class ProxyOfBuyTicket implements IBuyTicket{
//private BuyTicket buyTicket;①
private IBuyTicket iBuyTicket;
/*public ProxyOfBuyTicket(BuyTicket buyTicket) {
this.buyTicket = buyTicket;①
}*/
public ProxyOfBuyTicket(IBuyTicket iBuyTicket){
this.iBuyTicket = iBuyTicket;
}
@Override
public void buyTicket() {
System.out.println("黄牛拿了你的车票钱和代买费");
//buyTicket.buyTicket();①
iBuyTicket.buyTicket();
System.out.println("黄牛把票给你");
}
}
在这个代理类中,我们先是让它和之前的 BuyTicket类一样都实现了买票的接口IBuyTicket。然后再把接口定义为属性。实现接口的方法。而有争议的代码我也写出来了,也就是注释掉的代码。我们可以看到,区别就在于一个是把接口做为了属性,一个把对象作为属性。我们来写下主方法输出。
public class ProcessOfBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
ProxyOfBuyTicket proxyOfBuyTicket = new ProxyOfBuyTicket(buyTicket);
proxyOfBuyTicket.buyTicket();
}
}
输出结果为:.
黄牛拿了你的车票钱和代买费
买过年回家的票
黄牛把票给你
运行下注释的代码,替换原来的代码,就会发现是同样的输出结果。但是把对象作为属性的就是装饰器模式了。那为什么接口作为属性就是代理模式呢?因为代理模式中的代理类的其实就是帮助任何实现了买票接口的对象进行买票行为。而如果是注释的代码的话,就变成了只对BuyTicket这个类的对象进行代理。那就变成了装饰器模式了。讲到这里应该明白了吧,其实关键就是在于接口。
至于动态代理,是弥补了静态代理的不足。在这篇文章先暂时不描述了,展开来篇幅过长。以后再介绍。
文末分享一段歌词:
总有一条蜿蜒在童话镇里梦幻的河
分隔了理想分隔现实
又在前方的山口汇合
愿走在技术的人们包括我自己,一路向前,奔流不息