在设计模式中,适配器模式(英语:adapter pattern)有时候也称包装样式或者包装(英语:wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类能在一起工作,做法是将类自己的接口包裹在一个已存在的类中。
在GOF设计模式中,Adapter可以分为类模式和对象模式两种,类模式通过多重继承实现,对象模式通过委托实现。
结构
对象适配器模式
在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。
类适配器模式
这种适配器模式下,适配器继承自己实现的类(一般多重继承)。
模式概述
生活中的模式
如果你需要在国内使用香港的iPhone,你可能需要使用一个适配器。
适配器的作用:它位于港式插头和国标插座的中间,它的工作是将港式插座转换成国标插座,好让港式插头可以插进插座得到电力。
请一个翻译
意图
将一个接口转换成另一个接口,以符合客户的期望。
从而使得原本由于接口不兼容而不能一起工作的类可以一起工作。
该模式的目标是通过一个代理(这里是Adapter),在原来的类(Adaptee)和客户(Client)之间进行协调,从而达到兼容的目的。其核心是解决一致性的问题。
java 实现
在GOF设计模式中,Adapter可以分为类模式和对象模式两种,类模式通过多重继承实现,对象模式通过委托实现。
在Java中由于没有多重继承机制,所以要想实现类模式的Adapter,就要进行相应 的改变:通过继承Adaptee类实现Target接口方式实现。这种改变存在两个问题:1)Target必须是一个接口而不能是一个类,否则 Adapter无法implements实现;2)Adapter是继承Adaptee的实现,而不是私有继承,这就表示Adapter是一个 Adaptee的子类。
类模式/对象模式分析
A、表现在Adapter对Adaptee的特殊性要求:
类模式由于Adapter是Adaptee的子类,所以Adapter很方便重新定义Adaptee中的个别方法,以达到自己的特性需要。
对象模式由于Adapter不是Adaptee的子类,所以如果Adapter对Adaptee中的个别方法有特殊的需要,就要新建Adaptee的子类,而让Adapter使用这个子类。
B、表现在Adaptee的类层次扩展上:
类模式由于Adapter是Adaptee的子类,所以编译后就不能再更换所实现的父类Adaptee,因此如果有一个Adaptee的类层次结构,就要相应的有一个Adapter的类层次结构,且新扩展Adaptee时很不方便。
对象模式由于Adapter不是Adaptee的子类,而是通过使用的方式,所以在系统运行时仍然可以更换Adapter所使用的Adaptee,只要他们具有相同的类型。所以在新扩展Adaptee时很方便。
对象模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class Point {
private int coordinateX;
private int coordinateY;
public Point(int coordinateX, int coordinateY){
this.coordinateX = coordinateX;
this.coordinateY = coordinateY;
}
public String toString(){
return "Point[x=" + coordinateX + ",y=" + coordinateY + "]";
}
public int getCoordinateX() {
return coordinateX;
}
public int getCoordinateY() {
return coordinateY;
}
}
|
Shape接口对应Adapter 模式中的 Target
1
2
3
4
|
public interface Shape {
public Point getBottomLeftPoint();
public Point getTopRightPoint();
}
|
类TextView,工具箱中的文本组件类,已经存在的类,对应Adapter模式中的Adaptee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class TextView {
public int getCoordinateX() {
System.out.println("TextView.getCoordinateX()...");
return 10;
}
public int getCoordinateY() {
System.out.println("TextView.getCoordinateY()...");
return 20;
}
public int getHeight() {
System.out.println("TextView.getHeight()...");
return 30;
}
public int getWidth() {
System.out.println("TextView.getWidth()...");
return 40;
}
public boolean isEmpty(){
return false;
}
}
|
类TextShape,对象模式实现的Adapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class TextShape implements Shape {
private TextView textView;
public TextShape(TextView textView){
this.textView = textView;
}
//通过TextView的实例进行协调实现
public Point getBottomLeftPoint() {
System.out.println("TextShape.getBottomLeftPoint()...");
int coordinateX = textView.getCoordinateX();
int coordinateY = textView.getCoordinateY();
return new Point(coordinateX, coordinateY);
}
//通过TextView的实例进行协调实现
public Point getTopRightPoint() {
System.out.println("TextShape.getTopRightPoint()...");
int coordinateX = textView.getCoordinateX();
int coordinateY = textView.getCoordinateY();
int height = textView.getHeight();
int width = textView.getWidth();
return new Point(coordinateX + width, coordinateY + height);
}
}
|
类Client,Adapter模式的客户
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Client {
public static void main(String[] args){
System.out.println("Client.main begin ..........");
System.out.println("Client.main 以下是通过实例委托方式实现的Adapter");
Shape shape = new TextShape(new TextView());
Point bottomLeft = shape.getBottomLeftPoint();
Point topRight = shape.getTopRightPoint();
System.out.println("Client.main shape's bottomLeft:" + bottomLeft);
System.out.println("Client.main shape's topRight:" + topRight);
System.out.println("Client.main end ..........");
}
}
|
类模式实现
类Point、Shape、TextView相同,实现类模式的Adapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class TextShape2 extends TextView implements Shape {
//通过所继承的TextView,进行协调实现
public Point getBottomLeftPoint() {
System.out.println("TextShape2.getBottomLeftPoint()...");
int coordinateX = getCoordinateX();
int coordinateY = getCoordinateY();
return new Point(coordinateX, coordinateY);
}
//通过所继承的TextView,进行协调实现
public Point getTopRightPoint() {
System.out.println("TextShape2.getTopRightPoint()...");
int coordinateX = getCoordinateX();
int coordinateY = getCoordinateY();
int height = getHeight();
int width = getWidth();
return new Point(coordinateX + width, coordinateY + height);
}
//注意: 这一点体现了类模式的优势,可以很方便地重定义父类TextView中的方法
public int getCoordinateX() {
System.out.println("TextShape2.getCoordinateX()...");
return 100;
}
}
|
测试
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Client {
public static void main(String[] args){
System.out.println("Client.main begin ..........");
System.out.println(" Client.main 以下是通过类继承方式实现的Adapter");
Shape shape2 = new TextShape2();
bottomLeft = shape2.getBottomLeftPoint();
topRight = shape2.getTopRightPoint();
System.out.println("Client.main shape2's bottomLeft:" + bottomLeft);
System.out.println("Client.main shape2's topRight:" + topRight);
System.out.println("Client.main end ..........");
}
}
|
附录