设计模式之适配器模式
1、简介
《设计模式》一书中对Adapter模式的描述是这样的:
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使原本由于接口不兼容而不能一起工作的类可以一起工作。
2、例子
现在有这么一个场景,有三种形状的类分别是点(Point),线(Line)矩形(Rectangle),这三个类都有draw和display方法,但是相同的方法对应类的实现不同。客户(Client)对象可以调用具体类的具体方法。但为了程序的通用性以及后续的扩展(比如新增一个同样具有上述方法的Circle类),这里将三个类抽象成一个接口Shape。这样客户则可以以相同的方式处理所有对象而无需关注不同类之间的区别。客户调用draw或者display方法,由具体类根据自身特点负责完成相应的行为。实现代码如下
/**
* 标准接口
*
*/
public interface Shape {
public void display();
public void draw();
}
/**
* 实现标准接口,根据自身特点重写接口方法
*
*/
public class Point implements Shape{
@Override
public void display() {
System.out.println("Point display...");
}
@Override
public void draw() {
System.out.println("Point draw...");
}
}
/**
* 实现标准接口,根据自身特点重写接口方法
*
*/
public class Line implements Shape{
@Override
public void draw() {
System.out.println("Line draw...");
}
@Override
public void display() {
System.out.println("Line display...");
}
}
/**
* 实现标准接口,根据自身特点重写接口方法
*
*/
public class Rectangle implements Shape{
@Override
public void display() {
System.out.println("Rectangle display...");
}
@Override
public void draw() {
System.out.println("Rectangle draw...");
}
}
/**
* 客户类,以相同的方式处理不同的对象,不必关注具体的实现方式
*
*/
public class Client {
public static void main(String[] args) {
Shape point = new Point();
point.draw();
point.display();
Shape line = new Line();
line.draw();
line.display();
}
}
运行结果如图
假如这时又有新的需求,比如要增加一个新的形状Circle,同样也具有draw和display方法。此时,上面面向接口编程的好处就体现出来了,我们只需新建一个类,同样实现Shape这个接口并重写相应的方法即可完成扩展。但假如Circle类又不同于前面几个类,Circle类draw和display方法相对于其他类来说代码更复杂,我想偷懒怎么办?百度一下,你就知道。。。很幸运找到一个现成的又符合需求的代码,那就copy–>paste咯。等等,找到的这个类中方法的命名不符合我前面方法的命名规范,比如我的display方法它命名为show。我又懒得去修改代码,那怎么办,想办法适配呗。
实现如下:
1、先自己创建一个Circle类,同样实现Shape接口。假如我们找的类名字叫Round,此时我们需要在自己编写的类中引用Round类的实例对象,为什么?因为我们自己的Circle类中不想自己实现具体的方法,那么可以使用Round类中的方法来实现
2、Circle类中调用Round类中的方法来重写接口所需实现的方法
代码如下:
/**
* 这是找到的类,这个类的接口与标准接口(Shape)不匹配
* 在适配器模式中称为被适配者(Adaptee)
*
*/
public class Round {
//可以实现标准接口中display()功能,但接口不兼容
public void show(){
System.out.println("Circle display...");
}
//可以实现标准接口中draw()功能,但接口不兼容
public void paint()
{
System.out.println("Circle draw...");
}
}
/**
* 自己实现的实现标准接口的Circle类,在适配器模式中称为Adapter
* 该类持有Round类的实例,调用该实例完成接口中的方法
*
*/
public class Circle implements Shape{
//引用Round类
private Round round;
//初始化round对象
public Circle() {
round = new Round();
}
//调用round对象提供的方法来完成相应的接口中的方法
@Override
public void draw() {
round.paint();
}
@Override
public void display() {
round.show();
}
}
从这个实例中可以看出,适配器模式常见的用途就是保持多态性。在适配器模式中,Adapter(实例中Circle类)改变了Adaptee(实例中Round类)的接口,使得Adaptee与Adapter的基类Target(实例中的Shape接口)匹配