入门设计模式实战:第七章详解适配器模式——实例篇
最编程
2024-02-16 15:15:37
...
三个角色其中,适配器对象有三种,分别为类适配器、接口适配器、对象适配器
- 类适配器:使用继承的方式,将需要适配的类转换为目标接口的子类,实现目标接口的所有方法,同时继承适配类的实现,用以完成一些适配逻辑。
- 接口适配器:使用 组合 的方式将适配对象与目标接口组合,并在适配类中调用需要适配对象的方法。
- 对象适配器:
假设我们有一个圆形接口和一个正方形接口,但是客户端代码需要使用一个统一的接口来计算 不同形状的面积
2.1共同代码
2.1.1圆形接口和正方形接口—目标接口
即目标接口,需要适配的标准接口,含求面积方法
/**
* 圆形接口
*/
public interface Circle {
//获取半径
double getRadius();
}
/**
* 正方形接口
*/
public interface Square {
//获取边长
double getSideLength();
}
2.1.2具体的圆形和正方形类
public class CircleImpl implements Circle {
private double radius;
public CircleImpl(double radius) {
this.radius = radius;
}
@Override
public double getRadius() {
return radius;
}
}
public class SquareImpl implements Square {
private double sideLength;
public SquareImpl(double sideLength) {
this.sideLength = sideLength;
}
@Override
public double getSideLength() {
return sideLength;
}
}
2.2类适配器
定义一个类适配器,实现目标接口并继承被适配类,并在目标接口方法中调用被适配类的方法,从而将目标接口转换为被适配类的方法调用
/**
* 将圆形适配成正方形
*/
public class ShapeAdapter extends CircleImpl implements Square {
public ShapeAdapter(double radius) {
super(radius);
}
/**
* 实现目标接口方法,并调用被适配类的方法,
* 根据圆形的半径来计算一个等价面积的正方形的边长,返回可以代表相同面积的正方形的边长
*/
@Override
public double getSideLength() {
return getRadius() * 2 / Math.sqrt(2);
}
}
2.2.1测试
public class Client {
public static void main(String[] args) {
Circle circle = new CircleImpl(5); //实例半径为5的圆的对象
Square square = new ShapeAdapter(5); //
double circleArea = Math.PI * Math.pow(circle.getRadius(), 2); //计算半径为5的圆的面积:7.85
double squareArea = Math.pow(square.getSideLength(), 2); //将圆适配成正方形,
System.out.println("Circle area: " + circleArea); // 输出:Circle area: 78.53981633974483
System.out.println("Square area: " + squareArea); // 输出:Square area: 50.0
}
}
2.3接口适配器
定义一个接口适配器,将适配对象与目标接口组合,并在适配类中调用需要适配对象的方法。
public class CircleAdapter implements Square {
private Circle circle;
public CircleAdapter(Circle circle) {
this.circle = circle;
}
@Override
public double getSideLength() {
return circle.getRadius() * 2 / Math.sqrt(2);
}
}
2.3.1测试
public class Client {
public static void main(String[] args) {
Circle circle = new CircleImpl(5);
Square square = new CircleAdapter(circle);
double circleArea = Math.PI * Math.pow(circle.getRadius(), 2);
double squareArea = Math.pow(square.getSideLength(), 2);
System.out.println("Circle area: " + circleArea); // 输出:Circle area: 78.53981633974483
System.out.println("Square area: " + squareArea); // 输出:Square area: 50.0
}
}
2.4对象适配器
主要适用于需要被适配的接口中,只有用到个别接口,也就是说不需要实现它的全部接口。通过一个中间抽象类或接口实现。
2.4.1抽象适配器类
定义一个抽象适配器类,它实现了目标接口并提供了默认实现
public abstract class ShapeAdapter implements Square {
@Override
public double getSideLength() {
return 0;
}
}
2.4.2具体适配器类
定义一个具体的适配器类,它继承了抽象适配器类并实现了需要的目标接口方法,并调用被适配器的方法
public class CircleAdapter extends ShapeAdapter {
private Circle circle;
public CircleAdapter(Circle circle) {
this.circle = circle;
}
@Override
public double getSideLength() {
return circle.getRadius() * 2 / Math.sqrt(2);
}
}
3.优缺点
优点:
- 安全可靠:封装了旧接口,对客户端透明,客户端代码无需修改。
- 提高复用性:可以复用不兼容的类;可以对不同的类无需修改,就可以进行组合。
- 扩展性好:在应用程序开发过程中,可以增加新的适配器和被适配对象。
缺点:
- 过多的适配器会导致系统结构复杂。
- 如果适配器没有实现好,可能会拖慢整个系统的性能。
- 滥用适配器模式会导致系统设计紊乱。