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


    场景

    适配器模式(Adapter Pattern)

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

    适用场景:

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

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

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

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

    注:

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

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

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

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

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. //220V交流电
    3. public class AC220 {
    4.     public int outputAC220V(){
    5.         int output = 220;
    6.         System.out.println("输出交流电:"+output+"V");
    7.         return output;
    8.     }
    9. }

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

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. //5V直流电
    3. public interface DC5 {
    4.     int outputDC5V();
    5. }

    创建电源适配器类PowerAdapter

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class PowerAdapter implements DC5{
    3.     private AC220 ac220;
    4.     public PowerAdapter(AC220 ac220){
    5.         this.ac220 = ac220;
    6.     }
    7.     @Override
    8.     public int outputDC5V() {
    9.         int adapterInput = ac220.outputAC220V();
    10.         //变压器
    11.         int adapterOutput = adapterInput/44;
    12.         System.out.println("使用PowerAdapter输入AC:"+adapterInput+"V,输出DC:"+adapterOutput+"V");
    13.         return adapterOutput;
    14.     }
    15. }

    客户端测试代码

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class PowerAdapterTest {
    3.     public static void main(String[] args) {
    4.         DC5 dc5 = new PowerAdapter(new AC220());
    5.         dc5.outputDC5V();
    6.     }
    7. }

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

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

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

    创建统一的返回结果类ResultMsg

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. /**
    3.  * 返回结果类
    4.  */
    5. public class ResultMsg {
    6.     private int code;
    7.     private String msg;
    8.     private Object data;
    9.     public ResultMsg(int code, String msg, Object data) {
    10.         this.code = code;
    11.         this.msg = msg;
    12.         this.data = data;
    13.     }
    14.     public int getCode() {
    15.         return code;
    16.     }
    17.     public void setCode(int code) {
    18.         this.code = code;
    19.     }
    20.     public String getMsg() {
    21.         return msg;
    22.     }
    23.     public void setMsg(String msg) {
    24.         this.msg = msg;
    25.     }
    26.     public Object getData() {
    27.         return data;
    28.     }
    29.     public void setData(Object data) {
    30.         this.data = data;
    31.     }
    32. }

    老系统的登录代码如下

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class SiginService {
    3.     /**
    4.      * 注册方法
    5.      * @param username
    6.      * @param password
    7.      * @return
    8.      */
    9.     public ResultMsg regist(String username,String password){
    10.         return new ResultMsg(200,"注册成功",new Member());
    11.     }
    12.     /**
    13.      * 登录方法
    14.      * @param username
    15.      * @param password
    16.      * @return
    17.      */
    18.     public ResultMsg login(String username,String password){
    19.         return null;
    20.     }
    21. }

    为遵循开闭原则,不修改老系统的代码,开始重构代码。

    创建Member类

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class Member {
    3.     private String username;
    4.     private String password;
    5.     private String mid;
    6.     private String info;
    7.     public String getUsername() {
    8.         return username;
    9.     }
    10.     public void setUsername(String username) {
    11.         this.username = username;
    12.     }
    13.     public String getPassword() {
    14.         return password;
    15.     }
    16.     public void setPassword(String password) {
    17.         this.password = password;
    18.     }
    19.     public String getMid() {
    20.         return mid;
    21.     }
    22.     public void setMid(String mid) {
    23.         this.mid = mid;
    24.     }
    25.     public String getInfo() {
    26.         return info;
    27.     }
    28.     public void setInfo(String info) {
    29.         this.info = info;
    30.     }
    31. }

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

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class SignForThirdService extends  SiginService{
    3.     //qq登录
    4.     public ResultMsg loginForQQ(String openId){
    5.         //1、openId是全局唯一的,我们可以把它当成一个加长用户名
    6.         //2、自动生成默认密码
    7.         //3、注册-在原系统在创建一个用户
    8.         //4、调用原来的登录方法
    9.         return loginForRegist(openId,null);
    10.     }
    11.     //微信登录
    12.     public ResultMsg loginForWechat(String openId){
    13.         return null;
    14.     }
    15.     public ResultMsg loginForRegist(String username,String password){
    16.         super.regist(username,null);
    17.         return super.login(username,null);
    18.     }
    19. }

    客户端测试代码

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class SignForThirdServiceTest {
    3.     public static void main(String[] args) {
    4.         SignForThirdService signForThirdService  = new SignForThirdService();
    5.         //不改变原来的代码,也能兼容新的需求,还可以再加一层策略模式
    6.         signForThirdService.loginForQQ("badaodechengxvyuan");
    7.     }
    8. }

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

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

    首先创建LoginAdapter接口

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public interface LoginAdapter {
    3.     boolean support(Object adapter);
    4.     ResultMsg login(String id,Object adapter);
    5. }

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

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class LoginForQQAdapter implements LoginAdapter{
    3.     @Override
    4.     public boolean support(Object adapter) {
    5.         return adapter instanceof LoginForQQAdapter;
    6.     }
    7.     @Override
    8.     public ResultMsg login(String id, Object adapter) {
    9.         return null;
    10.     }
    11. }

    微信登录LoginForWechatAdapter

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class LoginForWechatAdapter implements LoginAdapter{
    3.     @Override
    4.     public boolean support(Object adapter) {
    5.         return adapter instanceof LoginForWechatAdapter;
    6.     }
    7.     @Override
    8.     public ResultMsg login(String id, Object adapter) {
    9.         return null;
    10.     }
    11. }

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

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public interface IPassportForThird {
    3.     /**
    4.      *  QQ登录
    5.      * @param id
    6.      * @return
    7.      */
    8.     ResultMsg loginForQQ(String id);
    9.     /**
    10.      * 微信登录
    11.      * @param id
    12.      * @return
    13.      */
    14.     ResultMsg loginForWechat(String id);
    15. }

    实现兼容PassportForThirdAdapter

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. /**
    3.  * 第三方登录自由适配
    4.  */
    5. public class PassportForThirdAdapter extends SiginService implements IPassportForThird{
    6.     @Override
    7.     public ResultMsg loginForQQ(String id) {
    8.         return processLogin(id,LoginForQQAdapter.class);
    9.     }
    10.     @Override
    11.     public ResultMsg loginForWechat(String id) {
    12.         return processLogin(id,LoginForWechatAdapter.class);
    13.     }
    14.     //这里用到了简单工厂模式和策略模式
    15.     private ResultMsg processLogin(String key,Classextends  LoginAdapter> clazz){
    16.         try {
    17.             LoginAdapter adapter = clazz.newInstance();
    18.             if(adapter.support(adapter)){
    19.                 return  adapter.login(key,adapter);
    20.             }else{
    21.                 return null;
    22.             }
    23.         } catch (Exception e) {
    24.             e.printStackTrace();
    25.         }
    26.         return null;
    27.     }
    28. }

    客户端测试代码

    1. package com.ruoyi.demo.designPattern.adapterPattern;
    2. public class PassportTest {
    3.     public static void main(String[] args) {
    4.         IPassportForThird passportForThird = new PassportForThirdAdapter();
    5.         passportForThird.loginForQQ("");
    6.     }
    7. }

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

    多场景适配时容易混淆。

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

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

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

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

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

  • 相关阅读:
    iOS调用文件app(file.app)选择文件和下载
    上周热点回顾(11.28-12.4)
    【学习总结】辐射、辐照等常见光学物理量的定义与关系
    折叠始祖摩托罗拉,困于“性价比”折叠屏
    centos6升级OpenSSH
    《用Go语言自制解释器》之第5章 宏系统
    计算机视觉40例之案例02人脸打码与解码
    【Day30】LeetCode算法 [769. 最多能完成排序的块 ] [2131. 连接两字母单词得到的最长回文串]
    Elasticsearch:调整搜索速度
    告诉你怎么让网站内容快速收录的技巧
  • 原文地址:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/127647999