问题:
如何解决不兼容的接口的问题,或者说如何提供一个稳定的接口给具有不同接口的相似组件?
解决方案:
通过一个中间的适配器对象使一个组件的原有接口转变成另一个接口。
(适配器模式实现及例子的代码均在git)
1. 继承与接口
使用普通的类继承或接口实现,可以通过父类对象引用子类实例的方式来实现运行时多态(Java 编译时多态和运行时多态)
public class Shape{ //shape类
public void display(){}
}
class Circle extends Shape{
public void display(){
/*draw Circle*/
}
}
class Rectangle extends Shape{
public void display(){
/*draw Rectangle*/
}
}
//显示图形
Shape a = new Circle();
a.display(); //显示一个圆
a = new Rectangle();
a.display(); //显示一个矩形
我们想增加画圆和画矩形的功能之外更多的图形显示功能,可以通过编写派生类来添加功能,但如果能使用已有的工具包就好了。
2. 接口不兼容
很幸运,我们找到了一个现成的软件工具包,可以画多边形等许多的图形,如果把它集成到我们的系统中来那就太好了!
可现实并没有那么简单!工具包提供的接口是这样的。
public class Poly {
public void init(){}
public void draw(){}
}
可是问题来了,Poly不是Shape的子类,而且Poly的显示代码甚至是这样的:init(); draw();
这下子我们无法用刚才的代码来重用工具包中的画图工具,我们遇到了接口不匹配的问题,有什么办法呢?
办法一:我们修改工具包中的图形类的接口,使它和我们的Shape类的接口相兼容,问题就解决了!
这种办法有什么问题:
1)为一个特殊的应用,就修改软件包的设计,显得并不聪明!
2)更何况通常情况下,我们没有工具包的完整源代码
但没关系,我们有更好的办法,就是适配器。
3. 适配器模式
适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
例子中适配器的实现:
public class PolyAdapter extends Shape{
private Poly poly;
public PolyAdapter(Poly p){
poly = p;
}
public void display(){
poly.init();
poly.draw();
}
}
Shape a = new PolyAdapter(new Poly());
a.display(); //显示一个多边形
参考资料:
1.《Applying UML and Patterns》
2.《软件分析与设计讲义》
3. Boss的PPT