关于java:如何快速搞定第三方登录且易扩展

5次阅读

共计 5339 个字符,预计需要花费 14 分钟才能阅读完成。

本文节选自《设计模式就该这样学》

1 应用类适配器重构第三方登录自在适配

咱们应用适配模式来实现一个理论的业务场景,解决理论问题。年纪略微大一点的小伙伴肯定经验过这样的过程。很早以前开发的老零碎应该都有登录接口,然而随着业务的倒退和社会的提高,单纯地依赖用户名明码登录显然不能满足用户需要。当初,大部分零碎都曾经反对多种登录形式,如 QQ 登录、微信登录、手机登录、微博登录等,同时保留用户名明码的登录形式。尽管登录模式丰盛,然而登录后的解决逻辑能够不用改,都是将登录状态保留到 Session,遵循开闭准则。首先创立对立的返回后果 ResultMsg 类。


/**
 * Created by Tom.
 */
public class ResultMsg {

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

    public ResultMsg(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public int getCode() {return code;}

    public void setCode(int code) {this.code = code;}

    public String getMsg() {return msg;}

    public void setMsg(String msg) {this.msg = msg;}

    public Object getData() {return data;}

    public void setData(Object data) {this.data = data;}
}

假如在老零碎中,解决登录逻辑的代码在 PassportService 类中。


public class PassportService {

    /**
     * 注册办法
     * @param username
     * @param password
     * @return
     */
    public ResultMsg regist(String username,String password){return  new ResultMsg(200,"注册胜利",new Member());
    }


    /**
     * 登录办法
     * @param username
     * @param password
     * @return
     */
    public ResultMsg login(String username,String password){return null;}

}

为了遵循开闭准则,不批改老零碎的代码。上面开启代码重构之路,创立 Member 类。


/**
 * Created by Tom.
 */
public class Member {

    private String username;
    private String password;
    private String mid;
    private String info;

    public String getUsername() {return username;}

    public void setUsername(String username) {this.username = username;}

    public String getPassword() {return password;}

    public void setPassword(String password) {this.password = password;}

    public String getMid() {return mid;}

    public void setMid(String mid) {this.mid = mid;}

    public String getInfo() {return info;}

    public void setInfo(String info) {this.info = info;}
}

咱们也不改变运行十分稳固的代码,创立 Target 角色 IPassportForThird 接口。


public interface IPassportForThird {ResultMsg loginForQQ(String openId);

    ResultMsg loginForWechat(String openId);

    ResultMsg loginForToken(String token);

    ResultMsg loginForTelphone(String phone,String code);

}

创立 Adapter 角色实现兼容,创立一个新的类 PassportForThirdAdapter,继承原来的逻辑。


public class PassportForThirdAdapter extends PassportService implements IPassportForThird {public ResultMsg loginForQQ(String openId) {return loginForRegist(openId,null);
    }

    public ResultMsg loginForWechat(String openId) {return loginForRegist(openId,null);
    }

    public ResultMsg loginForToken(String token) {return loginForRegist(token,null);
    }

    public ResultMsg loginForTelphone(String phone, String code) {return loginForRegist(phone,null);
    }

    private ResultMsg loginForRegist(String username,String password){if(null == password){password = "THIRD_EMPTY";}
        super.regist(username,password);
        return super.login(username,password);
    }
}

客户端测试代码如下。


public static void main(String[] args) {PassportForThirdAdapter adapter = new PassportForThirdAdapter();
        adapter.login("tom","123456");
        adapter.loginForQQ("sjooguwoersdfjhasjfsa");
        adapter.loginForWechat("slfsjoljsdo8234ssdfs");
}

2 应用接口适配器优化代码

通过这么一个简略的适配动作,咱们实现了代码兼容。当然,代码还能够更加优雅,依据不同的登录形式,创立不同的 Adapter。首先创立 LoginAdapter 接口。


public interface ILoginAdapter {boolean support(Object object);
    ResultMsg login(String id,Object adapter);
}

而后创立一个抽象类 AbstractAdapter 继承 PassportService 原有的性能,同时实现 ILoginAdapter 接口,再别离实现不同的登录适配,QQ 登录 LoginForQQAdapter。


public class LoginForQQAdapter extends AbstractAdapter{public boolean support(Object adapter) {return adapter instanceof LoginForQQAdapter;}

    public ResultMsg login(String id, Object adapter) {if(!support(adapter)){return null;}
        //accesseToken
        //time
        return super.loginForRegist(id,null);

    }

}

手机登录 LoginForTelAdapter。


public class LoginForTelAdapter extends AbstractAdapter{public boolean support(Object adapter) {return adapter instanceof LoginForTelAdapter;}

    public ResultMsg login(String id, Object adapter) {return super.loginForRegist(id,null);
    }
}

Token 主动登录 LoginForTokenAdapter。


public class LoginForTokenAdapter extends AbstractAdapter {public boolean support(Object adapter) {return adapter instanceof LoginForTokenAdapter;}

    public ResultMsg login(String id, Object adapter) {return super.loginForRegist(id,null);
    }
}

微信登录 LoginForWechatAdapter。


public class LoginForWechatAdapter extends AbstractAdapter{public boolean support(Object adapter) {return adapter instanceof LoginForWechatAdapter;}

    public ResultMsg login(String id, Object adapter) {return super.loginForRegist(id,null);
    }
}

接着创立适配器 PassportForThirdAdapter 类,实现目标接口 IPassportForThird 实现兼容。


public class PassportForThirdAdapter implements IPassportForThird {public ResultMsg loginForQQ(String openId) {return processLogin(openId, LoginForQQAdapter.class);
    }

    public ResultMsg loginForWechat(String openId) {return processLogin(openId, LoginForWechatAdapter.class);

    }

    public ResultMsg loginForToken(String token) {return processLogin(token, LoginForTokenAdapter.class);
    }

    public ResultMsg loginForTelphone(String phone, String code) {return processLogin(phone, LoginForTelAdapter.class);
    }


    private ResultMsg processLogin(String id,Class<? extends ILoginAdapter> clazz){
        try {ILoginAdapter adapter = clazz.newInstance();
            if (adapter.support(adapter)){return adapter.login(id,adapter);
            }
        } catch (Exception e) {e.printStackTrace();
        }
        return null;
    }
    
}

客户端测试代码如下。


public static void main(String[] args) {IPassportForThird adapter = new PassportForThirdAdapter();
        adapter.loginForQQ("sdfasdfasfasfas");
}

最初来看如下图所示的类图。

至此,在遵循开闭准则的前提下,咱们残缺地实现了一个兼容多平台登录的业务场景。当然,目前的这个设计并不完满,仅供参考,感兴趣的小伙伴们能够持续欠缺这段代码。例如适配器类中的参数目前是设置为 String,改为 Object[] 应该更正当。

学习到这里,置信小伙伴们会有一个疑难:适配器模式与策略模式如同区别不大?我要强调一下,适配器模式次要解决的是性能兼容问题,单场景适配可能不会和策略模式有比照。但简单场景适配大家就很容易混同。其实,大家有没有发现一个细节,笔者给每个适配器类都加上了一个 support() 办法,用来判断是否兼容,support() 办法的参数类型也是 Object,而 support() 来自接口。适配器类的实现逻辑并不依赖接口,齐全能够将 ILoginAdapter 接口去掉。而加上接口,只是为了代码标准。下面代码能够说是策略模式、简略工厂模式和适配器模式的综合使用。

【举荐】Tom 弹架构:珍藏本文,相当于珍藏一本“设计模式”的书

本文为“Tom 弹架构”原创,转载请注明出处。技术在于分享,我分享我高兴!
如果本文对您有帮忙,欢送关注和点赞;如果您有任何倡议也可留言评论或私信,您的反对是我保持创作的能源。关注微信公众号『Tom 弹架构』可获取更多技术干货!

正文完
 0