适配器模式
适配器模式将一个类的接口,转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以合作无间。
适配器模式是一个很简单的设计模式,在日常生活中有很多相似的例子,比如去欧洲国家,他们的插座都是三孔的,电压也不是220V,如果我们国产电器要使用的话,就必须使用适配器来转换接口和电压,如果有其他国家不同的标准,再提供一个其他适配器就好了,这样就不必为了兼容不同电器而设计多种电路。它的核心思想就是利用已有的对象,通过封装调用,转换成客户端需要的,能直接兼容的对象。
如果通过代码来解释的话,那么就是下面的样子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
* 欧洲国家标准,无法直接使用
*/
public class EuropePower {
// 三孔
public String getThreeHoles(){
return "ThreeHoles";
}
// 240V电压
public int getVoltage(){
return 240;
}
}
/**
* 国内标准,两孔,220V
*/
public interface ChinaPower {
public String getTwoHoles();
public int getVoltage();
}
/**
* 创建一个适配器
*/
public class PowerAdapter implements ChinaPower {
// 欧洲电力(被适配者)
EuropePower europePower;
public PowerAdapter(EuropePower europePower){
this.europePower = europePower;
}
// 调用此方法将得到两孔插座
public String getTwoHoles(){
String three = europePower.getThreeHoles();
// 将三孔转换成两孔
return threeToTwo(three);
}
// 调用此方法将得到220V电压
public int getVoltage(){
int v240 = europePower.getVoltage();
// 将240转成220
return v240To220(v240);
}
private String threeToTwo(String three){
// 具体实现...
return "two";
}
private int v240To220(int v240){
// 具体实现...
return 220;
}
}
// 测试
public class Test{
public void static main(String[] args){
// 将欧洲标准传给适配器
PowerAdapter adapter = new PowerAdapter(new EuropePower());
// 通过适配器获得国内标准的接口,两孔和220V电压
adapter.getTwoHoles();
adapter.getVoltage();
}
}
以上代码就是适配器模式,这个模式可以让客户端从实现中解藕,如果实现修改了,可以通过适配器将改变的地方封装起来,客户端就不必要跟着修改。适配器模式具有良好的设计原则:使用了组合,被适配者任何子类都可以搭配适配器使用。
上面的代码例子其实是对象适配器,还有一种是类适配器。对象适配器通过组合方式来拥有被适配的对象(被适配的对象可以是多个),然后进行转换。而类适配器通过继承来拥有被适配对象的实现(继承一个或多个),因为java是单继承,无法同时适配多个对象,所以这种模式适合多继承的语言,此处不做过多介绍。
外观模式
作者在适配器模式章节中顺便提到了外观模式,这个模式就更简单了。
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用。
这个模式就相当于快捷操作方式一样,只需要调用一下,程序就按顺序去做一系列的事情。比如原来你需要按顺序去调用1,2,3,4,5,6个方法才能得到一个结果,现在使用外观模式定义一个方法b,方法b中按顺序调用了1,2,3,4,5,6个方法,这样你直接调用b就行了,而不必要去调用6个方法。外观模式让客户端和一系列接口松耦合,让更加容易使用,同时如果需要,也可以直接调用子系统获得更多功能。
最少知识原则
最少知识原则:只和你的密友谈话
上面介绍的外观模式,其实蕴含着一种设计原则,那就是最少知识原则。就是说,当你设计一个系统时,不管是任何对象,你都要注意它所交互的类有哪些,并注意是如何交互的,不应该让太多的类耦合在一起,免得修改一部分,会影响到其他部分。
这个原则提供了一些指导方针,在一个对象中,我们应该只调用属于以下范围的方法:
- 该对象本身
- 被当作方法的参数而传递进来的对象
- 此方法所创建或实例化的任何对象
- 对象的任何组件,也就是通过组合方式拥有的属性对象
1
2
3
4
5
6
7
8
9
10
11
public float getTemp(){
// 不推荐,thermometer对象是通过station得到的
Thermometer thermometer = station.getThermometer();
return thermometer.getTemperature();
}
public float getTemp(){
// 推荐,通过组件station调用方法getTemperature,然后在station中去调用thermometer.getTemperature()
// 这样就将thermometer对象松耦合了
return station.getTemperature();
}
到这个章节,已经接触到了7个设计原则,分别是:
- 封装变化
- 多用组合,少用继承
- 针对接口编程,不针对实现编程
- 为交互对象之间的松耦合设计而努力
- 类应该对扩展开放,对修改关闭
- 依赖抽象,不要依赖具体类
- 只和密友交谈
不管是设计模式还是设计原则,在带来良好设计的同时,也可能带来一些负面影响,比如增加了很多对象封装,提高了系统的复杂性,降低了系统的性能,所以在实际工作中得学会取舍,达到一个平衡。