设计模式之适配器模式
适配器模式,也可以叫做包装模式,但包装模式不止适配器模式一个,装饰模式也是包装模式。这是一个比较简单的模式,直接先来看看适配器模式官方定义:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够一起工作。
先看一段代码:
public class Adapter_01 {
//己方用户接口
static class UserService{
public String getUserName(){
String name = "张三";
return name;
}
}
//三方的用户接口
static class ThrirdPartyUserService{
public Map<String, Object> getUserInfo(){
Map<String, Object> map = new HashMap<>();
map.put("userName","张三");
map.put("age",23);
return map;
}
}
}
以上代码中有两个类,一个是己方的用户接口,一个三方的用户接口,如果有个需求,要求将三方的用户信息导入己方的数据库中存储,那应该怎么办呢?(这里己方接口不能直接使用三方接口,类型不同)总不能将现有的己方接口全部按照三方用户的接口来改动吧,如果这样的话首先是改动太大,其次是己方的用户接口已经投入使用了,不适合大力改动,况且如果有一天突然不需要导入三方的用户了,那怎么办,又要重新改回来吗,这样怕是要崩溃的吧。这个时候就轮到适配器模式上场了,看一看下面这段代码:
public class Adapter_02 {
interface IUser{
public String getUserName();
}
//己方用户接口
static class UserService{
public String getUserName(){
String name = "张三";
return name;
}
}
interface IThrirdPartyUser{
public Map<String, Object> getUserInfo();
}
//三方的用户接口
static class ThrirdPartyUserService{
public Map<String, Object> getUserInfo(){
Map<String, Object> map = new HashMap<>();
map.put("userName","张三");
map.put("age",23);
return map;
}
}
//用户接口适配器
static class UserServiceAdapter extends ThrirdPartyUserService implements IUser{
@Override
public String getUserName(){
Map<String, Object> userInfo = this.getUserInfo();
return (String)userInfo.get("userName");
}
}
public static void main(String[] args) {
IUser user = new UserServiceAdapter();
user.getUserName();
}
}
以上示例做了部分改动,己方和三方的用户查询抽象成了一个接口,而适配器接口继承了三方用户接口,实现了己方用户接口。讲解下这样做的目的:
- 首先己方在获取三方的信息时,希望改动是最小的;
- 其次希望能够在新的接口中调用三方的接口,并将结果进行转换。
以上示例都做到了以上两点,实现IUser,就是遵循了里氏替换原则,这样同一个接口的实现类可以直接替换原有的类,并且不需要做其他任何变更,就可以达到最终想要的逻辑。
当然,以上是一种简单的,且只对应了三方的一个接口的模式,如果对应多个模式,由于java继承的限制,以上这种方式是行不通的,那就只有采用关联关系,让适配器同时关联三方的多个接口实例,并实现己方的接口,在接口中通过调用多个关联的对象方法,完成期望的结果,可以称为对象适配器,上一种方式称为类适配器。
使用场景:
该模式在设计之初不应该被考虑,只是作为后期功能补偿时才会用到
要使用该模式的话,相关的功能一定要遵守依赖倒置原则和里氏替换原则。