1、适配器模式
适配器模式是一种结构型设计模式,它能使接口不兼容的对象能够相互合作。 适配器可担任两个对象间的封装器,它会接收对于一个对象的调用,并将其转换为另一个对象可识别的格式和接口。
2、适配器模式适合应用场景
1)当你希望使用某个类,但是其接口与其他代码不兼容时,可以使用适配器类。
2)如果你需要复用这样的一个类,它们处于同一个继承体系,并且他们又有了额外的一些共同方法,但是这些共同的方法不是所有在这一个继承体系中的子类所具有的共性。
3、实现方式
1)确保至少有两个类的接口不兼容:
- 一个无法修改的功能性服务类。
- 一个或多个将受益于使用服务类的客户端类。
2)声明客户端接口,描述客户端如何与服务交互。
3)创建遵循客户端接口的适配类。所有方法暂时都为空。
4)在适配器类中添加一个成员变量用户保存服务对象的引用。通常情况下会通过构造函数对该成员变量进行初始化,但有时调用其方法将该变量传递给适配器会更方便。
5)依次实现适配器类客户端接口的所有方法。适配器会将实际工作委派给服务对象,自身只负责接口或数据格式的转换。
6)客户端必须通过客户端接口使用适配器,这样一来,可以在不影响客户端代码的情况下修改或扩展适配器。
4、优缺点
1)单一职责原则,你可以将接口或数据转换代码从程序主要业务逻辑中分离。
2)开闭原则。只要客户端代码通过客户端接口与适配器进行交互,你就能在不修改现有客户端代码的情况下在程序中添加新类型的适配器。
3)代码整体复杂度增加,因为你需要新增一系列接口和类。有时直接更改服务类使其与其他代码兼容会更简单。
5、Java代码示例
让方钉适配圆钉
这个简单的例子展示了适配器如何让不兼容的对象相互合作 。
圆孔类RoundHole.java
public class RoundHole {
private double radius;
public RoundHole(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
//判断钉是否能进入孔中
public boolean fits(RoundPeg peg) {
boolean result;
result = (this.getRadius() >= peg.getRadius());
return result;
}
}
圆钉类RoundPeg.java
public class RoundPeg {
private double radius;
public RoundPeg() {}
public RoundPeg(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
}
方钉类SquarePeg.java
public class SquarePeg {
private double width;
public SquarePeg(double width) {
this.width = width;
}
public double getWidth() {
return width;
}
public double getSquare() {
double result;
result = Math.pow(this.width, 2);
return result;
}
}
方钉到圆孔的适配器类SquarePegAdpter.java
//适配器继承了圆钉
public class SquarePegAdapter extends RoundPeg {
private SquarePeg peg;
public SquarePegAdapter(SquarePeg peg) {
this.peg = peg;
}
@Override
public double getRadius() {
double result;
// Calculate a minimum circle radius, which can fit this peg.
result = (Math.sqrt(Math.pow((peg.getWidth() / 2), 2) * 2));
return result;
}
}
客户端demo.java
public class Demo {
public static void main(String[] args) {
// Round fits round, no surprise.
RoundHole hole = new RoundHole(5);
RoundPeg rpeg = new RoundPeg(5);
if (hole.fits(rpeg)) {
System.out.println("Round peg r5 fits round hole r5.");
}
SquarePeg smallSqPeg = new SquarePeg(2);
SquarePeg largeSqPeg = new SquarePeg(20);
// hole.fits(smallSqPeg); // Won't compile.
// Adapter solves the problem.
SquarePegAdapter smallSqPegAdapter = new SquarePegAdapter(smallSqPeg);
SquarePegAdapter largeSqPegAdapter = new SquarePegAdapter(largeSqPeg);
if (hole.fits(smallSqPegAdapter)) {
System.out.println("Square peg w2 fits round hole r5.");
}
if (!hole.fits(largeSqPegAdapter)) {
System.out.println("Square peg w20 does not fit into round hole r5.");
}
}
}