场景:
先来介绍一张图,关于欧洲和和亚洲的电源接口:
假定:有个中国人去欧洲旅行,他带的是两个插头的标准手机充电插头,但是欧洲没有这样的插座,他又两种选择
第一种选择:买一个适配欧洲插座的插头
欧洲插头接口标准:
package com.tangbaobao.design.pattern.struct.adapter.example2;
/**
* @author tangxuejun
* @version 2019-04-25 13:06
*/
public interface EuropeSocket {
public void connect();
}
苹果欧洲插头接口:
package com.tangbaobao.design.pattern.struct.adapter.example2;
/**
* @author tangxuejun
* @version 2019-04-25 13:07
*/
public class AppleEuropeSocket implements EuropeSocket {
@Override
public void connect() {
System.out.println("我是欧洲标准三个插孔");
}
}
然后这样用:
package com.tangbaobao.design.pattern.struct.adapter.example2;
/**
* @author tangxuejun
* @version 2019-04-25 13:11
*/
public class MainTest {
public static void main(String[] args) {
//使用欧洲插入去连接
AppleEuropeSocket appleAsiaSocket = new AppleEuropeSocket();
conn(appleAsiaSocket);
}
//暴露给客户端的方法,只支持欧洲插头接口标准
public static void conn(EuropeSocket asiaSocket) {
asiaSocket.connect();
}
}
买一套充电器得80英镑,回国之后又没有别的用处,是不是很浪费,好在还给我们别的选择,可以买一个转接头,只需5英镑,也就是在亚洲插头前面加一个欧洲接口头,也可以为手机充电,这也就是我们程序中的适配器
适配器模式
- 定义:将一个类的接口转换为客户希望另外一个类的接口(使原本不兼容的类可以一起工作)
使用场景:
- 已经存在的类,它的方法和需求不匹配时(方法和结果类似)
- 不是软件设计阶段考虑的设计模式,而是随着软件维护,由于不同产品,不同厂家造成功能类似而接口不同情况下的解决方案
优点:
- 能提高类的透明性和复用,现有的类复用不需要改变
- 目标类和适配器类解耦,提高程序的可扩展性
缺点:
- 适配器编写过程中需要全面考虑,可能会增加系统的复杂性
- 增加系统代码可读性的难度
扩展:
- 对象适配器模式
- 类适配器模式
第二种:使用适配器模式为手机充电:
这个适配器一边肯定是实现了欧洲充电头的接口,另外一边用来对接亚洲插头接口:
所以这个适配器肯定有两个部分组成:
- 实现欧洲插头标准接口
- 提供亚洲接头的链接
亚洲苹果充电头(被适配类):
package com.tangbaobao.design.pattern.struct.adapter.example2;
/**
* @author tangxuejun
* @version 2019-04-25 13:18
*/
public class AppleAsiaSocket {
public void connect() {
System.out.println("我是亚洲标准两插口的");
}
}
转接器(适配器):
package com.tangbaobao.design.pattern.struct.adapter.example2;
/**
* @author tangxuejun
* @version 2019-04-25 13:07
* EuropeSocket 是目标适配接口
*/
public class Adapter implements EuropeSocket {
private AppleAsiaSocket appleSocket = new AppleAsiaSocket();
@Override
public void connect() {
appleSocket.connect();
System.out.println("我把亚洲插头转换为欧洲插头啦");
}
}
使用:
package com.tangbaobao.design.pattern.struct.adapter.example2;
/**
* @author tangxuejun
* @version 2019-04-25 13:11
*/
public class MainTest {
public static void main(String[] args) {
//使用欧洲插入去连接
AppleEuropeSocket appleAsiaSocket = new AppleEuropeSocket();
conn(appleAsiaSocket);
//用实现了目标接口的适配器去连接
Adapter adapter = new Adapter();
conn(adapter);
}
//暴露给客户端的方法
public static void conn(EuropeSocket asiaSocket) {
asiaSocket.connect();
}
}
UML类图: