• (工厂+策略)实现登录功能


    原始代码

    业务层UserService

    @Service
    public class UserService {
    
        public LoginResp login(LoginReq loginReq){
    
            if(loginReq.getType().equals("account")){
                System.out.println("用户名密码登录");
    
                //执行用户密码登录逻辑
    
                return new LoginResp();
    
            }else if(loginReq.getType().equals("sms")){
                System.out.println("手机号验证码登录");
    
                //执行手机号验证码登录逻辑
    
                return new LoginResp();
            }else if (loginReq.getType().equals("we_chat")){
                System.out.println("微信登录");
    
                //执行用户微信登录逻辑
    
                return new LoginResp();
            }
            LoginResp loginResp = new LoginResp();
            loginResp.setSuccess(false);
            System.out.println("登录失败");
            return loginResp;
        }
    }
    

    注意:我们重点讲的是设计模式,并不是登录的逻辑,所以以上代码并没有真正的实现登录功能

    问题分析

    • 业务层代码大量使用到了if...else,在后期阅读代码的时候会非常不友好,大量使用if...else性能也不高
    • 如果业务发生变更,比如现在新增了QQ登录方式,这个时候需要修改业务层代码,违反了开闭原则

    解决:

    使用工厂方法设计模式+策略模式解决

    改进代码

    要将上述代码改为使用工厂模式和策略模式,首先我们需要定义几个关键元素:策略接口、具体策略类、策略工厂以及修改UserService来使用这些策略。下面是改造后的代码示例:

    1. 定义策略接口

    public interface LoginStrategy {
        LoginResp login(LoginReq loginReq);
    }
    

    2. 创建具体策略类

    AccountLoginStrategy

    @Service
    public class AccountLoginStrategy implements LoginStrategy {
        @Override
        public LoginResp login(LoginReq loginReq) {
            System.out.println("用户名密码登录");
            // 执行用户密码登录逻辑
            return new LoginResp();
        }
    }
    

    SmsLoginStrategy

    @Service
    public class SmsLoginStrategy implements LoginStrategy {
        @Override
        public LoginResp login(LoginReq loginReq) {
            System.out.println("手机号验证码登录");
            // 执行手机号验证码登录逻辑
            return new LoginResp();
        }
    }
    

    WeChatLoginStrategy

    @Service
    public class WeChatLoginStrategy implements LoginStrategy {
        @Override
        public LoginResp login(LoginReq loginReq) {
            System.out.println("微信登录");
            // 执行用户微信登录逻辑
            return new LoginResp();
        }
    }
    

    3. 实现策略工厂

    @Service
    public class LoginStrategyFactory {
        
        @Autowired
        private AccountLoginStrategy accountLoginStrategy;
        
        @Autowired
        private SmsLoginStrategy smsLoginStrategy;
        
        @Autowired
        private WeChatLoginStrategy weChatLoginStrategy;
        
        public LoginStrategy getLoginStrategy(String type) {
            switch (type) {
                case "account":
                    return accountLoginStrategy;
                case "sms":
                    return smsLoginStrategy;
                case "we_chat":
                    return weChatLoginStrategy;
                default:
                    throw new IllegalArgumentException("Invalid login type");
            }
        }
    }
    

    4. 修改UserService使用策略

    @Service
    public class UserService {
    
        @Autowired
        private LoginStrategyFactory loginStrategyFactory;
    
        public LoginResp login(LoginReq loginReq){
            LoginStrategy strategy = loginStrategyFactory.getLoginStrategy(loginReq.getType());
            if(strategy == null){
                LoginResp loginResp = new LoginResp();
                loginResp.setSuccess(false);
                System.out.println("登录失败: 无效的登录类型");
                return loginResp;
            }
            return strategy.login(loginReq);
        }
    }
    

    通过这种方式,UserService不再直接包含各种登录逻辑,而是通过策略工厂获取对应的策略对象来处理登录请求,这使得代码更加灵活和可扩展。如果需要添加新的登录方式,只需增加一个新的策略类并修改工厂类即可,无需修改UserService的逻辑。

  • 相关阅读:
    2019CCPC网络赛 杭电 6705 path(题解+代码)
    mybatis参数为0识别为空字符串的查询处理
    产品需求交付质量保证的“七重门”
    leetcode 50. Pow(x, n) (快速幂)
    go语言包管理和变量保护
    4、基础入门——30余种加密编码进制&web&数据库&系统&代理
    用了半年chromium,说说心得
    大白话解析 Dubbo3.0
    LeetCode 42. 接雨水
    我要是早点用Python做副业就好了......
  • 原文地址:https://www.cnblogs.com/XiaYu-Ye/p/18226237