适配器(Adapter)模式
用官方的话定义:将一个类的接口转换成客户希望的另外一个接口。主的目的是为了兼容性,让原本因接口不匹配、不兼容、不能一起工作的两个类可以协同工作。
所以说,设计这个模式的目的就是让原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
分为:类适配器模式、对象的适配器模式、接口的适配器模式。
合成复用原则:在系统中尽量使用关联关系来替代继承关系,因此大部分结构型模式都是对象结构型模式。
在这定义:
需要适配的类,接口,对象我们称之为基础(Basic)
适配器:(Adapter)
最终客户所期待的目标,目标可以是具体的或抽象的类,也可以是接口。(Target)
类适配器模式
简单来说:Adapter类,通过继承 Basic类,实现 Target 类接口,完成Basic->Target的适配。
//目标电压
public interface TargetVoltage {
//客户目标
int printVoltage();
}
//当前电压
class Basic {
public int printVoltage(){
int voltage=220;
System.out.println("当前电压为"+voltage+"V");
return voltage;
}
}
//适配器
class Adapter extends Basic implements TargetVoltage{
@Override
public int printVoltage(){
int voltage=super.printVoltage();
int target=voltage/10;
System.out.println("转换成"+target+"V");
return target;
}
}
//小米手机
class XiaMi {
public void chongDian(TargetVoltage targetVoltage){
if(targetVoltage.printVoltage()>30){
System.out.println("电压太高,不能充电");
}else{
System.out.println("电压刚刚好,正在充电...");
}
}
}
//Client
public class Client{
public static void main(String[] args) {
//手机需要冲电
XiaMi phone = new XiaMi();
//电压太高,需要适配器
TargetVoltage targetVoltage = new Adapter();
//充电
phone.chongDian(targetVoltage);
}
}
当前电压为220V
转换成22V
电压刚刚好,正在充电...
所以说所以,类适配器需要继承Basic类算是一个缺点, 因为这要求目标必须是接口,有一定局限性; 且Basic类的方法在Adapter中都会暴露出来,也增加了使用的成本。但同样由于其继承了Baisc类,所以它可以根据需求重写Basic类的方法,使得Adapter的灵活性增强了。
对象适配器模式(重点)
基本思路和类的适配器模式相同,只是将Adapter类作修改,这次不继承Basic类,而是拥有Basic类的实例,来解决兼容性的问题。 即:持有 Basic类的实例对象,实现目标接口,完成Basic->目标(Target)的适配。
适配器:
public class Adapter2 implements TargetVoltage{
private Basics basic;
public Adapter2(Basics basic){
this.basic = basic;
}
@Override
public int printVoltage() {
int voltage = basic.printVoltage();
System.out.println("适配器开始工作...");
int tarVoltage = voltage / 10;
System.out.println("当前电压为"+tarVoltage+"V");
return tarVoltage;
}
}
手机:
public class HuaWei {
public void chongDian(TargetVoltage targetVoltage){
if(targetVoltage.printVoltage()>30){
System.out.println("电压太高,无法充电...");
}else{
System.out.println("电压刚刚好,正在充电...");
}
}
}
客户:
public class MobileClient {
public static void main(String[] args) {
HuaWei huaWei = new HuaWei();
TargetVoltage targetVoltage = new Adapter2(new Basics());
huaWei.chongDian(targetVoltage);
}
}
当前电压为220V
适配器开始工作...
当前电压为22V
电压刚刚好,正在充电...
它解决了类适配器必须继承类(Basic)的局限性问题,也不再强求Target必须是接口。 同样的它使用成本更低,更灵活。
接口适配器模式
当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求,它适用于一个接口不想使用其所有的方法的情况。
Basic:
public class Basic {
int printVoltage220V(){
int voltage=220;
System.out.println("当前电压为"+voltage+"V");
return voltage;
}
}
接口:
public interface TargetVoltage {
int printVoltage5V();
int printVoltage10V();
int printVoltage15V();
int printVoltage20V();
}
抽象类:
//中间适配器
public abstract class MiddleAdapter implements TargetVoltage{
protected Basic basic;
public MiddleAdapter(Basic basic){
this.basic=basic;
}
@Override
public int printVoltage5V() {
return basic.printVoltage220V();
}
@Override
public int printVoltage10V() {
return basic.printVoltage220V();
}
@Override
public int printVoltage15V() {
return basic.printVoltage220V();
}
@Override
public int printVoltage20V() {
return basic.printVoltage220V();
}
}
适配器:
//适配器
public class Adapter extends MiddleAdapter{
public Adapter(Basic basic) {
super(basic);
}
public int printVoltage10V(){
int voltage=super.basic.printVoltage220V();
System.out.println("适配器正在工作...");
int target=voltage/22;
System.out.println("当前电压为"+target+"V");
return target;
}
}
测试:
public class Client {
public static void main(String[] args) {
Adapter adapter=new Adapter(new Basic());
adapter.printVoltage10V();
}
}
总之:
类适配器,以类给Adapter,就是将basic当做类继承。
对象适配器,以对象给Adapter里,将basic作为一个对象持有。
接口适配器,以接口给Adapter里,将basic作为一个接口实现。
Adapter模式最大的作用还是将原本不兼容的接口融合在一起工作。 但是在实际开发中,实现起来不拘泥于本文介绍的三种经典形式。