设计模式相关文章,用于整理网络中对应的设计模式的一些解读。

实例

以下实例来源于微信公众号(Java知音)文章,设计模式是什么鬼(适配器)

顾名思义,适配器,得适应当前的不同配置,解决兼容性问题。我们生活中充满了各种各样的适配器,上网用的调制解调器(modem)就是一种数模转换的适配器,俗称“猫”,不过现在都是光猫了,也就是光信号和电信号的互相转化,其实道理是一样的,还有各种变压器也属于电压转换的适配器。

适配器
适配器

如果觉得还不够形象可以看一下家里的电器,比如你的电视是两项插头,墙上的插孔是三项插孔怎么办?哦,有人说把插头掰弯强行插入!那如果是三项插头接两项插孔呢?把零线插针拔了!呃,我只能说这是暴力破解!违反设计模式原则。言归正传,我们还是不要随便破坏现有的类,那我们需要的是一个转换器,用优雅微妙的方式化解这种不兼容情况。

适配器
适配器

举个例子,我们开始代码部分,先写墙上的三项插孔接口,命名TriplePin

1
2
3
4
public interface TriplePin {
//参数分别为火线live,零线null,地线earth
public void electrify(int l, int n, int e);
}

我们只定义三插孔标准electrify(通电)方法,三个参数分别是火线、零线、地线,很简单吧,同样地接下来是两项插孔接口,只是少了地线,命名DualPin

1
2
3
public interface DualPin {
public void electrify(int l, int n);//这里没有地线
}

请注意,这个并不是我们的墙上的目标接口,而是电视机的两插标准。好了继续,我们的TV登场了,用的是两项插头,当然它实现的是DualPin的标准,Let's keep it simple,命名TV

1
2
3
4
5
6
7
8
9
public class TV implements DualPin {

@Override//既然是两项插头,当然实现两项插标准
public void electrify(int l, int n) {
System.out.println("火线通电:" + l);
System.out.println("零线通电:" + n);
}

}

那么问题来了,墙上的接口是三插标准,电视实现的是两插标准,无法通电。怎么办?把电视拆了重新修改实现三插标准么?暴力份子你又来?答案显然是否定的,既然是设计模式,果断转换插头啊!好,写个Adapter解决他们之间不可调和的矛盾。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Adapter implements TriplePin {

private DualPin dualPinDevice;

//创建适配器地时候,需要把双插设备接入进来
public Adapter(DualPin dualPinDevice) {
this.dualPinDevice = dualPinDevice;
}

//适配器实现的是目标接口
@Override
public void electrify(int l, int n, int e) {
//实际上调用了被适配设备的双插通电,地线e被丢弃了。
dualPinDevice.electrify(l, n);
}

}

注意了最关键最精华的部分来了,private DualPin dualPinDevice;代码意味着这个适配器内部是有一个双插接口的,对于任何双插标准的设备都是可以兼容的OK吗?不明白赶紧看看你家里的适配器。public Adapter(DualPin dualPinDevice) {...}方法的代码完成的过程实际就是你把电视插头接入Adapter了,其实适配器并不在意是什么设备,洗衣机冰箱都可以的,只要是双插标准就可以接入(第一节讲过的多态概念)。electrify()通电方法实现的是三插标准,但方法体内部dualPinDevice.electrify(l, n);实际上是在给“某个设备”(是什么设备就看你接什么了)的双插供电,地线e那个参数是用不上的,所以就没有接通,很清晰透彻吧?

当然,除了以上的注入插头的方式(对象适配),还有另一种更简单的方式叫做“类适配器”我们来看下:

1
2
3
4
5
6
7
8
public class ClassAdapter extends TV implements TriplePin{

@Override
public void electrify(int l, int n, int e) {
super.electrify(l, n);
}

}

看出来区别没有?这里并没有注入插头(对象组合),而是把电视机给继承了,这样就可以直接调用父类(TV)的双插通电而不是注入进来去调用,缺点大家也看到了,这适配器继承为TV儿子专用了,洗衣机是用不了啦,作死?其实也不是完全不好,要看具体应用场景哈。

至此,我们的Adapter就差不多完成了,以后再也不用破坏插头了,因为这样重写接口或者修改类的代价太大,如果其他类还有依赖的话,那统统要修改,引入了没有必要的重构,总之暴力修改是违反设计模式的基本原则的,开闭原则,指的就是对扩展开放,而对修改关闭,也就是说不要去改动原始类,而是扩展现有功能,提供另一种机制让整个系统实现想要的功能。

最后说下那些概念,归类,名字,什么“类适配器”,“对象适配器”啊,其实,理解不了就算了无所谓,真正的意义在于怎么样在实际工作中灵活运用,实现方式是无穷无尽的,道不清说不尽的,没必要太纠结它到底叫什么,归于哪一类,掌控其背后的道才是最根本的,正如李耳君所言:“道可道,非常道。名可名,非常名。”