Pulpcode

捕获,搅碎,拼接,吞咽

0%

从python到java设计模式-适配器模式

适配器模式是一种非常常用的模式。

我们常常所理解的设计模式是,你在一开始就想好了系统的构架,然后用设计模式去构建你的构架,奈何真实的项目,往往有你想不到的地方,新的改动不断的加入,这个时候就需要一些模式来满足这种打补丁的需求。

所以我认为适配器模式的真实场景是这样的:

你的现有系统跑的很好,这个时候突然来了一个新的接口,你要融合到你现有的系统设计中去,因为你现有系统运行的很好,你不想对其做任何修改,这时你就需要适配器模式,来将这个新的接口包装成现有系统能理解的样子,让它们根本不知道来了这样一个新接口。

但更好的做法是,你一开始就想到,你的服务,将来可能有更多的三方接口去调用,所以一开始就做一个适配器,来让你的服务使用适配器,而非直接使用三方。说白了,适配器就承担了缓冲的功能。

你的调用方式,一开始是A->B,只不过现在变成了 A -> C -> B, C作为适配器,解耦了A和B。

适配器模式算一种结构模式,虽然有很多结构模式跟适配器模式类似(比如桥接模式),但是它们出发点和所要解决的问题却是不同的。适配器模式强调将一个类的接口,转换成所希望的另一个接口。就像我们最早提到的,一个新的接口接入到现有系统中来,但是我们确实不想做过多的改动。而适配器就可以将代价降到最小。

所以现实生活的例子就是插座了。它确实生动形象的表达了适配器的作用。

java 实现

在设计模式这本书中,提到的是这样一个例子:

现有的绘图编辑器程序,容许用户绘制和排列基本元素:

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

Interface Ishape{

public void BoundingBox();

public void CreateMainpulator();
}


class Line implements Ishape{
public void BoundingBox(){
xxxx
}

public void CreateMainpulator(){
xxxx
}
}

class Circle implements Ishape{
public void BoundingBox(){
xxxx
}

public void CreateMainpulator(){
xxxx
}
}

而对于一个TextView而言,它并没有提供上面的这两个方法。我们不能重写一个TextView,因为它的很多部分是可以重用的,这个时候,就需要把TextView适配成Shape。

《设计模式》这本书上提到了C++使用多重继承,然而java并没有多重继承,所以只能使用接口配属性的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Class TextView{

void getExtent();
}

class TextShape implements Ishape{
private TextView textView;

public void BoundingBox(){
return textView.getExtent();
}

public void CreateMainpulator(){
return new TextMainpulator();
}
}

python 实现

python看上去实现起来很简单,你需要创建了一个新类,作为适配器来重用你的现有类。而且因为鸭子类型,你并不需要继承某个接口。

不过为了让接口确实被适配了,还是建议继承接口 + raise NotImplementedError

1
2
3
4
5
6
7
8
9

class Sharp(object):
void BoundingBox(){
raise NotImplementedError
}

void CreateMainpulator(){
raise NotImplementedError
}