设计模式之适配器模式(adapter)

适配器模式

不是软件设计阶段的模式,随着软件的维护造成,类或者接口不兼容的情况下衍生出适配器来处理问题
和策略模式很像,也可以理解为是策略模式的实现
策略模式专注于应用多策略,适配器专注于兼容
目标类和适配器解耦增加扩展性
提高类的复用性和透明性,现有类不需要改变
编写过程中会增加代码复杂性,难以理解

案例

多种方式登录

老版本用户密码登录服务

public class LoginService {

    public void login(String username,String password){
        System.out.println("使用username+password登录");
    }
}

第三方登录接口

public interface ILoginForThird {

    void QQLogin(String openid);

    void wechatLogin(String openid);

    void phoneLogin(String phone,String code);
}

适配器接口

/**
 * 适配器模式,可以不用接口
 * 这里只是模拟真实场景
 */
public interface LoginAdapter {

    boolean supports(LoginAdapter adapter);

    void login(LoginAdapter adapter, Map<String,Object> loginParam);
}

适配器实现

// 手机登录适配器
public class PhoneLoginAdapter implements LoginAdapter{
    @Override
    public boolean supports(LoginAdapter adapter) {
        return adapter instanceof PhoneLoginAdapter;
    }

    @Override
    public void login(LoginAdapter adapter, Map<String, Object> loginParam) {
        login((String) loginParam.get("phone"), (String) loginParam.get("code"));
    }

    private void login(String phone,String code){
        System.out.println("使用手机 - phone="+phone+"&code="+code+"登录");
    }
}
// QQ登录适配器
public class QQLoginAdapter implements LoginAdapter{
    @Override
    public boolean supports(LoginAdapter adapter) {
        return adapter instanceof QQLoginAdapter;
    }

    @Override
    public void login(LoginAdapter adapter, Map<String, Object> loginParam) {
        login((String) loginParam.get("openid"));
    }

    private void login(String openid){
        System.out.println("使用QQ - openid="+openid+"登录");
    }
}
// 微信登录适配器
public class WechatLoginAdapter implements LoginAdapter{
    @Override
    public boolean supports(LoginAdapter adapter) {
        return adapter instanceof WechatLoginAdapter;
    }

    @Override
    public void login(LoginAdapter adapter, Map<String, Object> loginParam) {
        login((String) loginParam.get("openid"));
    }

    private void login(String openid){
        System.out.println("使用WECHAT - openid="+openid+"登录");
    }
}

第三方登陆实现

public class LoginForThirdAdapter extends LoginService implements ILoginForThird {

    @Override
    public void QQLogin(String openid) {
        Map<String,Object> loginParam = new HashMap<>();
        loginParam.put("openid",openid);
        // 策略模式
        processLogin(loginParam,QQLoginAdapter.class);
    }

    @Override
    public void wechatLogin(String openid) {
        Map<String,Object> loginParam = new HashMap<>();
        loginParam.put("openid",openid);
        processLogin(loginParam, WechatLoginAdapter.class);
    }

    @Override
    public void phoneLogin(String phone, String code) {
        Map<String,Object> loginParam = new HashMap<>();
        loginParam.put("phone",phone);
        loginParam.put("code",code);
        processLogin(loginParam, PhoneLoginAdapter.class);
    }
    // 简单工厂模式
    private void processLogin(Map<String,Object> loginParam , Class<? extends LoginAdapter> clazz){

        try {
            LoginAdapter loginAdapter = clazz.newInstance();
            if (loginAdapter.supports(loginAdapter)){
                loginAdapter.login(loginAdapter,loginParam);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

Main

public class Main {

    public static void main(String[] args) {
        LoginForThirdAdapter adapter = new LoginForThirdAdapter();
        // 兼容老版本登录
        adapter.login("bl3air","12343");
        // 支持新版本
        adapter.wechatLogin("12334");
        adapter.QQLogin("12334");
        adapter.phoneLogin("11111111","423122");
    }
}

print

使用username+password登录
使用WECHAT - openid=12334登录
使用QQ - openid=12334登录
使用手机 - phone=11111111&code=423122登录

应用

spring aop 通知(AdvisorAdapter)
spring mvc HandleAdapter


设计模式之适配器模式(adapter)
https://www.blaaair.com/archives/she-ji-mo-shi-zhi-shi-pei-qi-mo-shi-adapter
作者
Glo6f
发布于
2022年01月01日
许可协议