设计模式-适配器模式在Java中的使用示例

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 设计模式-适配器模式在Java中的使用示例,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

场景

适配器模式(Adapter Pattern)

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

适用场景:

1、已经存在的类的方法和需求不匹配(方法结果相同或类似)的情况。

2、适配器模式不是软件初始阶段考虑的设计模式,是随着软件的发展,由于不同产品、不同厂家

造成功能类似而接口不同的问题的解决方案。

3、生活中类似的场景比如电源插座转换头、手机充电转换头、显示器转换头、电压转换等。

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

适配器模式示例-电压转换

民用电220V交流电,但手机使用5V直流电,因此给手机充电时需要使用电源适配器进行转换。

创建AC220类,表示220V交流电

package com.ruoyi.demo.designPattern.adapterPattern;

//220V交流电
public class AC220 {
    public int outputAC220V(){
        int output = 220;
        System.out.println("输出交流电:"+output+"V");
        return output;
    }
}

创建DC5接口,表示5V直流电

package com.ruoyi.demo.designPattern.adapterPattern;

//5V直流电
public interface DC5 {
    int outputDC5V();
}

创建电源适配器类PowerAdapter

package com.ruoyi.demo.designPattern.adapterPattern;

public class PowerAdapter implements DC5{

    private AC220 ac220;
    public PowerAdapter(AC220 ac220){
        this.ac220 = ac220;
    }
    @Override
    public int outputDC5V() {
        int adapterInput = ac220.outputAC220V();
        //变压器
        int adapterOutput = adapterInput/44;
        System.out.println("使用PowerAdapter输入AC:"+adapterInput+"V,输出DC:"+adapterOutput+"V");
        return adapterOutput;
    }
}

客户端测试代码

package com.ruoyi.demo.designPattern.adapterPattern;

public class PowerAdapterTest {
    public static void main(String[] args) {
        DC5 dc5 = new PowerAdapter(new AC220());
        dc5.outputDC5V();
    }
}

适配器模式示例-重构第三方登录自由适配

系统初始只有登录接口,随着业务发展,需要新增第三方登录比如QQ登录和微信登录。

登录后台的处理逻辑不改,同样将登录状态保存到session。

创建统一的返回结果类ResultMsg

package com.ruoyi.demo.designPattern.adapterPattern;

/**
 * 返回结果类
 */
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;
    }
}

老系统的登录代码如下

package com.ruoyi.demo.designPattern.adapterPattern;

public class SiginService {
    /**
     * 注册方法
     * @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类

package com.ruoyi.demo.designPattern.adapterPattern;

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;
    }
}

再创建一个新的类继承原来的代码

package com.ruoyi.demo.designPattern.adapterPattern;

public class SignForThirdService extends  SiginService{

    //qq登录
    public ResultMsg loginForQQ(String openId){
        //1、openId是全局唯一的,我们可以把它当成一个加长用户名
        //2、自动生成默认密码
        //3、注册-在原系统在创建一个用户
        //4、调用原来的登录方法
        return loginForRegist(openId,null);
    }

    //微信登录
    public ResultMsg loginForWechat(String openId){
        return null;
    }

    public ResultMsg loginForRegist(String username,String password){
        super.regist(username,null);
        return super.login(username,null);
    }
}

客户端测试代码

package com.ruoyi.demo.designPattern.adapterPattern;

public class SignForThirdServiceTest {
    public static void main(String[] args) {
        SignForThirdService signForThirdService  = new SignForThirdService();
        //不改变原来的代码,也能兼容新的需求,还可以再加一层策略模式
        signForThirdService.loginForQQ("badaodechengxvyuan");
    }
}

通过如上即可实现代码的兼容。

但是代码还可以再优化,不同的登录方式创建不同的Adapter

首先创建LoginAdapter接口

package com.ruoyi.demo.designPattern.adapterPattern;

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

然后,分别实现不同的登录方式,QQ登录LoginForQQAdapter

package com.ruoyi.demo.designPattern.adapterPattern;

public class LoginForQQAdapter implements LoginAdapter{
    @Override
    public boolean support(Object adapter) {
        return adapter instanceof LoginForQQAdapter;
    }

    @Override
    public ResultMsg login(String id, Object adapter) {
        return null;
    }
}

微信登录LoginForWechatAdapter

package com.ruoyi.demo.designPattern.adapterPattern;

public class LoginForWechatAdapter implements LoginAdapter{
    @Override
    public boolean support(Object adapter) {
        return adapter instanceof LoginForWechatAdapter;
    }

    @Override
    public ResultMsg login(String id, Object adapter) {
        return null;
    }
}

然后创建第三方登录兼容接口IPassportForThrid

package com.ruoyi.demo.designPattern.adapterPattern;

public interface IPassportForThird {
    /**
     *  QQ登录
     * @param id
     * @return
     */
    ResultMsg loginForQQ(String id);

    /**
     * 微信登录
     * @param id
     * @return
     */
    ResultMsg loginForWechat(String id);
}

实现兼容PassportForThirdAdapter

package com.ruoyi.demo.designPattern.adapterPattern;

/**
 * 第三方登录自由适配
 */
public class PassportForThirdAdapter extends SiginService implements IPassportForThird{
    @Override
    public ResultMsg loginForQQ(String id) {
        return processLogin(id,LoginForQQAdapter.class);
    }

    @Override
    public ResultMsg loginForWechat(String id) {
        return processLogin(id,LoginForWechatAdapter.class);
    }

    //这里用到了简单工厂模式和策略模式
    private ResultMsg processLogin(String key,Class<? extends  LoginAdapter> clazz){

        try {
            LoginAdapter adapter = clazz.newInstance();
            if(adapter.support(adapter)){
                return  adapter.login(key,adapter);
            }else{
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

客户端测试代码

package com.ruoyi.demo.designPattern.adapterPattern;

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

适配器模式主要解决的是功能兼容问题,单场景适配时不会和策略模式对比,但是

多场景适配时容易混淆。

上面给每个适配器都加上了一个support()方法,用来判断是否兼容。

设计模式-简单工厂模式、工厂模式、抽象工厂模式在Java中的使用示例:

设计模式-简单工厂模式、工厂模式、抽象工厂模式在Java中的使用示例_霸道流氓气质的博客-CSDN博客

设计模式-策略模式在Java中的使用示例:

设计模式-策略模式在Java中的使用示例_霸道流氓气质的博客-CSDN博客

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135877.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!