适配器模式
介绍
就是把一个类的接口变换成客户端所期待的一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
- Adapter:适配器。
- Adaptee:被适配者。
- Target:目标对象。
优点
也是一种包装模式,与装饰模式同样具有包装的功能,此外,对象适配器模式还具有委托的意思。总的来说,适配器模式属于补偿模式,专用来在系统后期扩展、修改时使用。
缺点
过多的使用适配器,会让系统非常凌乱,不易整体进行把握。例如,明明调用的是A接口,内部却被适配成了B接口的实现,一个系统如果太多出席这种情况,会非常麻烦。因此如果不是很必要,可以不适用适配器模式,而是直接对系统进行重构。
分类
- 类适配器:通过继承来实现适配器功能。
- 对象适配器:通过组合来实现适配器功能。
- 接口适配器:通过抽象类来实现适配器功能。不同于类和对象适配。
应用场景
类适配器和对象适配器的使用场景一致,主要应用场景是:
- 使用一个已经存在的类,但却不符合现有的接口规范,无法直接访问的情况。
- 将一个类设计为可重用的类。
接口适配器的使用场景:
- 要使用接口中的某个或某些方法,实现接口并实现接口中的方法,可以使用抽象类来实现接口,并对方法进行实现,然后再继承这个抽象类并通过重写想用的方法。
实例
类适配器实例
通过继承来实现
客户端调用的接口 Teacher :
package com.spring.adapter.classes;
/**
* 客户端调用的接口
* @author 17610
*/
public interface Teacher {
//客户端调用的方法
public void work();
}
被适配的接口 Student :
package com.spring.adapter.classes;
/**
* 真正要调用的接口(被适配的)
* @author 17610
*/
public interface Student {
//真正要调用的方法
public void study();
}
Student的实现类:
package com.spring.adapter.classes;
/**
* 被适配的接口的实现类
* (其实就是创建了一个类的子类来满足我们不能直接调用原有类的需要)
* @author 17610
*/
public class StudentImpl implements Student{
//重写父类中的方法
@Override
public void study() {
//可以添加新的业务
System.out.println("这里实现了被适配的类的方法");
}
}
适配器类 Adapter :
package com.spring.adapter.classes;
/**
* 适配器类
* @author 17610
*/
public class Adapter extends StudentImpl implements Teacher{
//重写父类的方法
@Override
public void work() {
//继承父类的方法,所以这里直接调用了父类StudentImpl中的方法
study();
}
}
测试类:
package com.spring.adapter.classes;
/**
* 测试类(模拟客户端调用)
* @author 17610
*/
public class ClientTest {
public static void main(String[] args) {
//创建客户端调用对象
Teacher t = new Adapter();
//执行请求
t.work();
}
}
运行效果为:
这里实现了被适配的类的方法
对象适配器实例
通过组合实现
客户端调用的接口:
package com.spring.adapter2;
/**
* 用户调用的接口
* @author 17610
*
*/
public interface ClientTarget {
//处理具体业务的方法
public void work();
}
被适配器的类:
package com.spring.adapter2;
/**
* 被适配的类(原本就存在的类)
* @author 17610
*
*/
public class Adaptee {
//原本就存在的方法
public void specificWork(){
System.out.println("这里是原本就存在的方法。");
}
}
适配器类:
package com.spring.adapter2;
/**
* 适配器类
* @author 17610
*
*/
public class Adapter implements ClientTarget{
//维护一个被适配的对象
private Adaptee adaptee;
//有参构造
public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
//重写实现的接口中的方法(客户端调用接口的方法)
@Override
public void work() {
//调用原本存在的类中原本存在的方法
adaptee.specificWork();
}
}
测试类:
package com.spring.adapter2;
/**
* 测试类(模拟客户端调用的类)
* @author 17610
*
*/
public class ClientTest {
public static void main(String[] args) {
//创建客户端调用的接口对象
ClientTarget ct = new Adapter(new Adaptee());
//处理请求
ct.work();
}
}
运行效果:
这里是原本就存在的方法。
接口适配器实例
通过抽象类实现。
目标接口:
package com.spring.adapter.intefaces;
/**
* 目标接口
* @author 17610
*
*/
public interface Study {
//定义的方法
public void study();
public void work();
}
适配器类:
package com.spring.adapter.intefaces;
/**
* 适配器类(抽象类)
* @author 17610
*
*/
public abstract class Adapter implements Study{
public void study(){}
public void work(){}
}
适配器类的实现类:
package com.spring.adapter.intefaces;
/**
* 适配器类的实现类
* @author 17610
*
*/
public class AdapterImpl extends Adapter{
public void study(){
System.out.println("实现study方法被调用");
}
public void work(){
System.out.println("实现work方法被调用");
}
}
测试类:
package com.spring.adapter.intefaces;
/**
* 测试类
* @author 17610
*
*/
public class ClientTest {
public static void main(String[] args) {
//创建一个目标类对象
Study stu = new AdapterImpl();
//执行请求
stu.study();
System.out.println("--------------");
stu.work();
}
}
运行结果:
实现study方法被调用
--------------
实现work方法被调用