java设计模式————适配器模式,怎么加上第三方登陆接口

适配器模式(Adapter Pattern)

指将一个类的接口转换成客户期望的另一个接口,使原本的接口不兼容的类可以一起工作。

属于结构型设计模式。

适用场景:

1.已经存在的类,它的方法和需求不匹配的情况。

2.适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品,不同厂家造成功能类似而接口不相同情况下的解决方案。

代码场景:

现在需要给系统加上第三方登陆,要在保留原登陆接口不变的情况下加上。

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 16:07 2020-3-12
 */
@Data
@AllArgsConstructor
public class MsgResult {

    private int code;
    private Object data;
    private String msg;

    public static MsgResult success(Object data){
        return new MsgResult(200,data,"成功");
    }

    public static MsgResult fail(Object data){
        return new MsgResult(404,data,"失败");
    }
}

/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption  相当于系统已经写好的代码,不去动它
 * @E-Mail : [email protected]
 * @Date : Created in 13:38 2020-3-14
 */
public class LoginService {

    //用户名,密码登陆方法
    public MsgResult login(String username,String password){
        return null;
    }

    //注册方法
    public MsgResult register(String username,String password){
        return login(username,password);
    }
}

/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption 新的登陆接口
 * @E-Mail : [email protected]
 * @Date : Created in 14:02 2020-3-14
 */
public interface NewLogin {

    public MsgResult loginQQ(String id);

    public MsgResult loginWechat(String id);
}

/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption 适配器方式
 * @E-Mail : [email protected]
 * @Date : Created in 13:54 2020-3-14
 */
public class LoginForThird extends LoginService implements NewLogin{


    @Override
    public MsgResult loginQQ(String id) {
        System.out.println("通过qq登陆");
        return null;
    }

    @Override
    public MsgResult loginWechat(String id) {
        System.out.println("通过微信登陆");
        return null;
    }
}

这就是一个最简单的适配器模式,当然也很像静态代理模式,因为设计模式是一种思想而不是局限于代码,只是用代码的方式来实现这种思想,当然,这样肯定是太简单了,那么我们现在来实现下业内比较流行的增加第三方登陆的方式。

第一步:我们保留原系统login不变

/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption  相当于系统已经写好的代码,不去动它
 * @E-Mail : [email protected]
 * @Date : Created in 13:38 2020-3-14
 */
public class LoginService {

    //用户名,密码登陆方法
    public MsgResult login(String username,String password){
        System.out.println("用户pc登陆");
        return null;
    }

    //注册方法
    public MsgResult register(String username,String password){
        return login(username,password);
    }
}

第二步:我们加上一个适配器接口,和所有的适配器

/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption 在适配器中,这个接口可有可无,不要和模板模式混淆
 *              模板模式一定是抽象类,这里只是一个接口
 * @E-Mail : [email protected]
 * @Date : Created in 14:38 2020-3-14
 */
public interface LoginAdapter {

    //判断是否是需要调用的适配器,是否兼容
    /**
     * 为什么要这个方法,因为适配器可能会有多个,比如再来个注册适配器
     * @param adapter
     * @return
     */
    boolean support(Object adapter);

    public MsgResult login(String id,Object adapter);
}
/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption
 * @E-Mail : [email protected]
 * @Date : Created in 14:41 2020-3-14
 */
public class LoginQQAdapter implements LoginAdapter{
    @Override
    public boolean support(Object adapter) {
        return adapter instanceof LoginQQAdapter;
    }

    @Override
    public MsgResult login(String id, Object adapter) {
        //写自己qq登陆的逻辑
        System.out.println("通过qq登陆");
        return null;
    }
}

/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption
 * @E-Mail : [email protected]
 * @Date : Created in 14:42 2020-3-14
 */
public class LoginWechatAdapter implements LoginAdapter {
    @Override
    public boolean support(Object adapter) {
        return adapter instanceof LoginWechatAdapter;
    }

    @Override
    public MsgResult login(String id, Object adapter) {
        //写微信自己登陆的逻辑
        System.out.println("通过微信登陆");
        return null;
    }
}


/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption
 * @E-Mail : [email protected]
 * @Date : Created in 13:54 2020-3-14
 */
public class LoginForThird extends LoginService implements NewLogin{


    //这里可以继续使用策略模式来优化
    @Override
    public MsgResult loginQQ(String id) {
        return loginAdapterFactory(id,LoginQQAdapter.class);
    }

    @Override
    public MsgResult loginWechat(String id) {
        return loginAdapterFactory(id,LoginWechatAdapter.class);
    }

    //简单工厂
    public MsgResult loginAdapterFactory(String id,Class <? extends LoginAdapter> clazz){
        try {
            LoginAdapter adapter = clazz.newInstance();
            if(adapter.support(adapter)){
                return adapter.login(id,adapter);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return MsgResult.fail(null);
    }
}

/**
 * @Author Darker
 * @Note 我心净处,何处不是西天。
 * @Descrption
 * @E-Mail : [email protected]
 * @Date : Created in 17:55 2020-3-13
 */
public class AdapterTest {
    public static void main(String[] args) {
        LoginForThird loginForThird = new LoginForThird();
        loginForThird.login("xiaoming","123456");
        loginForThird.loginQQ("dsadas");
        loginForThird.loginWechat("1556");
    }
}

这样符合开闭原则,又用适配器解决了其它第三方登陆的需求,同时如果需要其它的登陆,也只需要继续增加适配器就可以了。

看一下类图:

我们来看看spring-aop中用到的策略模式:

 

 

springAop中的消息通知中就使用了这个适配器模式 ,选择你要的适配器,然后看是在方法前通知还是方法后通知。

再来看看spring-mvc中的适配器:

 

 

这里的适配器主要是在servlet里面使用 ,有兴趣的小伙伴可以去DispatcherServlet中的doDispatch中看看。

总结:

优点:

1.能提高类的透明性和复用,现有的类的复用不需要去做改变。

2.目标类和适配器类的解耦。

3.很多场景中符合开闭原则。

缺点:

1.需要全面考虑,而且很可能增加系统的复杂性。

2.增加阅读代码的难度,过多使用可能使代码变的很乱。

发布了27 篇原创文章 · 获赞 1 · 访问量 3639

猜你喜欢

转载自blog.csdn.net/qq_40111437/article/details/104858328