What?
Convert the interface of a class into another interface
that the clients expect. Adapter lets classes work together
that could not otherwise because of incompatible inter-
faces. ——GOF
不改变客户端代码,通过使用适配器去包装、兼容一个客户端无法直接兼容的接口.
一般分为:类适配器 与 对象适配器
UML图(对象适配器)
How(对象适配器)
先来个例子:
比如我接到需求要开发一套图形系统,于是我设计
统一接口(为了多态性)Shape,
Shape接口的行为是: display()
其中有一些实现类如,Triangle等等
/**
* 这个接口是暴漏给客户端的,我们希望使用这个接口
*
* Target
*/
public interface Shape {
void display();
void drawing();
}
/*
* Target 实现类
*/
public class Triangle implements Shape {
@Override
public void display() {
System.out.println("Triangle display");
}
@Override
public void drawing() {
System.out.println("Triangle drawing");
}
}
当我在设计Circle这个对象时,发现小王已经写过了类似实现,并且逻辑完全一致,那我当然要复用了。小王的代码:
/**
* 不兼容的接口
*
* Adaptee :需要被适配的接口
*/
public interface Graph {
void displayGraph();
void drawingGraph();
}
这个Circle是我希望兼容的!
/**
*
* Adaptee :需要被适配的接口
*/
public class Circle implements Graph {
@Override
public void displayGraph() {
System.out.println("Circle displayGraph");
}
@Override
public void drawingGraph() {
System.out.println("Circle drowingGraph");
}
}
但是,他的接口、方法参数各种不一致,难道我要改动?!怎么面向客户端用?于是我想使用Adapter,来复用小王的实现,同时满足我的代码设计结构,让客户端不该写代码直接使用。
/**
* CircleAdapter包装了不兼容的Graph接口,并以Shape的形式暴漏给客户端
*/
public class CircleAdapter implements Shape {
private Graph circle;// 组合的方式 不兼容的Circle
//使用组合的好处是,任何Graph的子类都和以在适配器中使用
public CircleAdapter(Graph circle) {
this.circle = circle;
}
@Override
public void display() {
circle.displayGraph();
}
@Override
public void drawing() {
circle.drawingGraph();
}
}
/**
* 客户端面向(Target)Shape接口编程,由于Graph的实现类Circle中有我们可以复用的逻辑,
*
* 所以我们想把这个Circle转化为Shape, 以兼容客户端使用
*
*/
public class ClientToShape {
public static void main(String[] args) {
Shape triangle = new Triangle();
testShape(triangle);
Shape circleAdapter = new CircleAdapter(new Circle());
testShape(circleAdapter);
}
static void testShape(Shape shape) {
shape.display();
shape.drawing();
}
}
客户端向Shape发送请求,得到返回。完全没有觉察到是Adapter起了转换作用,把请求发到被适配者上并得到返回。
target:Shape
适配器:CircleAdapter;
被适配对象:(Graph)Circle
可以想一想,如果我们的目标是Graph,怎么让面向Graph定义实现的客户端使用Triangle呢?
类适配器
标准的UML图是需要多继承的,但是java不支持多继承,严格意义上并不适用,但是targe可以是个interface,算是扩展吧
当我们使用类适配器时,代码:
/**
*
* 使用继承的方式将不兼容的Circle引入
*/
public class CircleClassAdapter extends Circle implements Shape {
@Override
public void display() {
super.displayGraph();
}
@Override
public void drawing() {
super.displayGraph();
}
}
Adapter与Facade的比较:
相同:都是将老的系统包装起来。都是在新接口中复用老的系统代码。
不同:Adapter要做的是将一个错误的已经存在的接口转化为目前新的接口,我调新的接口也同样做老的事情(而且代码复用)。Facade纯粹是通过组合单纯的整合、复用老的系统代码。
总之:
Facade简化系统,而Adapter是一个已有接口转化为另一个新接口。