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


    场景

    适配器模式(Adapter Pattern)

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

    适用场景:

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

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

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

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

    注:

    博客:
    https://blog.csdn.net/badao_liumang_qizhi
    关注公众号
    霸道的程序猿
    获取编程相关电子书、教程推送与免费下载。

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

    民用电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中的使用示例:

    https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/127539695

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

    https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/127622238

  • 相关阅读:
    arangodb安装
    ubuntu安装java方法
    设置代理
    自动机
    统计学习基本理论知识(一)
    条件随机场(四)
    条件随机场(三)
    hive安装
    GC root & 使用MAT分析java堆
    jinfo介绍
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/16850368.html
Copyright © 2020-2023  润新知