老榕树网站建设教学,静态网站入侵,怎么做直播室的网站,商城免费建站系统各位开发者好#xff0c;我是在项目里被登录功能折磨过无数次的老码农。还记得三年前接手一个多端登录项目#xff0c;用户名密码、微信、手机号验证码三种登录方式挤在一个if-else里#xff0c;新增支付宝登录时整整改了 17 处代码#xff0c;最后还漏了一处校验 —— 从此…各位开发者好我是在项目里被登录功能折磨过无数次的老码农。还记得三年前接手一个多端登录项目用户名密码、微信、手机号验证码三种登录方式挤在一个if-else里新增支付宝登录时整整改了 17 处代码最后还漏了一处校验 —— 从此发誓再也不用 面条代码 处理登录逻辑。今天就把结合工厂模式和策略模式的优雅实现分享出来带你从需求分析到 Spring Boot 实战彻底告别登录模块的维护噩梦。一、需求分析当产品说 我们要支持 10 种登录方式1. 典型登录场景代码里的 联合国假设我们要实现一个支持三种登录方式的系统用户名密码登录需要校验密码加密、账号是否锁定微信扫码登录需要调用微信开放平台 API校验授权码手机号验证码登录需要生成验证码、校验有效期和正确性传统写法是写一个LoginService用if-else判断登录类型public String login(String loginType, MapString, Object params) { if (password.equals(loginType)) { // 用户名密码登录逻辑 } else if (wechat.equals(loginType)) { // 微信登录逻辑 } else if (sms.equals(loginType)) { // 手机号登录逻辑 } else { throw new IllegalArgumentException(不支持的登录类型); } }这种写法的问题在于扩展性差新增登录方式要改if-else违反开闭原则职责混乱所有逻辑挤在一个类里可读性差复用困难不同登录方式的公共逻辑如用户校验无法抽取2. 设计模式选择策略模式解耦算法工厂模式创建实例策略模式将每种登录方式封装成独立策略类实现统一接口调用者无需关心具体实现 工厂模式通过工厂类根据登录类型创建对应的策略实例避免调用者直接 new 对象二、Spring Boot 项目搭建先搭好 舞台1. 创建 Spring Boot 项目添加 Web 依赖项目结构如下src/main/java/com/example/login ├── config │ └── StrategyConfig.java // 策略Bean配置 ├── controller │ └── LoginController.java // 登录控制器 ├── factory │ └── LoginStrategyFactory.java // 登录策略工厂 ├── model │ └── LoginRequest.java // 登录请求参数 ├── service │ ├── impl │ │ ├── PasswordLoginStrategy.java // 用户名密码策略 │ │ ├── WechatLoginStrategy.java // 微信策略 │ │ └── SmsLoginStrategy.java // 手机号策略 │ └── LoginStrategy.java // 登录策略接口 └── Application.java2. 定义统一登录策略接口public interface LoginStrategy { // 登录类型标识如password、wechat String getLoginType(); // 登录方法参数用Map传递不同登录方式的参数 String execute(MapString, Object params); }三、策略模式实现每种登录方式都是 独立演员1. 用户名密码登录策略Service publicclass PasswordLoginStrategy implements LoginStrategy { Override public String getLoginType() { returnpassword; } Override public String execute(MapString, Object params) { String username (String) params.get(username); String password (String) params.get(password); // 模拟密码校验实际应从数据库查询密码解密 if (!123456.equals(password)) { thrownew IllegalArgumentException(密码错误); } // 模拟用户校验 checkUserLocked(username); return登录成功用户名密码; } private void checkUserLocked(String username) { // 调用用户服务检查账号是否锁定 System.out.println(检查用户 username 是否锁定); } }2. 微信扫码登录策略Service publicclass WechatLoginStrategy implements LoginStrategy { Override public String getLoginType() { returnwechat; } Override public String execute(MapString, Object params) { String authCode (String) params.get(authCode); // 模拟调用微信接口获取用户信息 String openId callWechatApi(authCode); // 模拟数据库查询用户绑定关系 String userId getUserIdByOpenId(openId); if (userId null) { thrownew IllegalArgumentException(微信账号未绑定系统用户); } return登录成功微信扫码; } private String callWechatApi(String authCode) { // 实际应调用微信开放平台API System.out.println(调用微信接口authCode authCode); returnwechat_open_id_123; } }3. 手机号验证码登录策略Service publicclass SmsLoginStrategy implements LoginStrategy { Override public String getLoginType() { returnsms; } Override public String execute(MapString, Object params) { String phone (String) params.get(phone); String code (String) params.get(code); // 模拟验证码校验实际应从Redis获取 if (!666888.equals(code)) { thrownew IllegalArgumentException(验证码错误); } // 模拟用户校验 checkPhoneRegistered(phone); return登录成功手机号验证码; } private void checkPhoneRegistered(String phone) { // 检查手机号是否注册 System.out.println(检查手机号 phone 是否注册); } }四、工厂模式实现让 导演 决定用哪个 演员1. 登录策略工厂类Component publicclass LoginStrategyFactory { privatefinal MapString, LoginStrategy strategyMap; // 通过Spring依赖注入获取所有LoginStrategy实现类 public LoginStrategyFactory(MapString, LoginStrategy strategyMap) { this.strategyMap strategyMap; } public LoginStrategy getStrategy(String loginType) { LoginStrategy strategy strategyMap.get(loginType); if (strategy null) { thrownew IllegalArgumentException(不支持的登录类型 loginType); } return strategy; } }这里利用 Spring 的自动装配将所有Service标记的LoginStrategy实现类注入到strategyMap中键为 Bean 名称默认是类名首字母小写如passwordLoginStrategy但我们在策略类中通过getLoginType()返回自定义的类型标识所以需要在配置类中调整 Bean 名称2. 策略 Bean 配置关键Configuration publicclass StrategyConfig { Bean(passwordStrategy) // 自定义Bean名称 public LoginStrategy passwordLoginStrategy() { returnnew PasswordLoginStrategy(); } Bean(wechatStrategy) public LoginStrategy wechatLoginStrategy() { returnnew WechatLoginStrategy(); } Bean(smsStrategy) public LoginStrategy smsLoginStrategy() { returnnew SmsLoginStrategy(); } }然后在策略类中重写getLoginType()返回和前端约定的类型标识如 password并在工厂类中建立类型标识到 Bean 的映射// 修改工厂类的构造方法建立正确映射 public LoginStrategyFactory(MapString, LoginStrategy strategyMap) { this.strategyMap new HashMap(); strategyMap.forEach((beanName, strategy) - this.strategyMap.put(strategy.getLoginType(), strategy) ); }五、控制器集成对外提供统一接口1. 登录请求参数类public class LoginRequest { private String loginType; // 登录类型如password、wechat private MapString, Object params; // 具体参数不同登录方式不同 // 省略getter/setter }2. 登录控制器RestController RequestMapping(/login) publicclass LoginController { privatefinal LoginStrategyFactory factory; Autowired public LoginController(LoginStrategyFactory factory) { this.factory factory; } PostMapping public String login(RequestBody LoginRequest request) { String loginType request.getLoginType(); MapString, Object params request.getParams(); LoginStrategy strategy factory.getStrategy(loginType); return strategy.execute(params); } }六、测试验证三种登录方式轻松切换1. 用户名密码登录请求{ loginType: password, params: { username: user123, password: 123456 } }2. 微信扫码登录请求{ loginType: wechat, params: { authCode: wechat_auth_code_456 } }3. 新增登录方式比如支付宝登录只需新增AlipayLoginStrategy类并实现接口无需修改现有代码Service(alipayStrategy) public class AlipayLoginStrategy implements LoginStrategy { Override public String getLoginType() { return alipay; } Override public String execute(MapString, Object params) { // 支付宝登录逻辑 return 登录成功支付宝; } }七、核心优势让代码具备 抗需求变化体质1. 策略模式的好处解耦算法每种登录逻辑独立在策略类中可读性强易于扩展新增登录方式只需添加新策略类符合开闭原则方便测试可以单独测试每个策略类无需关心其他逻辑2. 工厂模式的好处封装创建逻辑调用者无需知道策略类的创建细节集中管理实例通过 Spring 管理策略 Bean支持依赖注入和生命周期管理3. 结合 Spring Boot 的优势自动装配通过Service和MapString, LoginStrategy自动收集所有策略 Bean类型安全工厂类在运行时检查登录类型是否合法避免NullPointerException八、最佳实践这些细节别忽略1. 参数校验前置在控制器中先对loginType和params做基础校验比如必填参数检查避免策略类中重复校验2. 公共逻辑抽取如果多种登录方式有公共逻辑如登录成功后的 Token 生成可以创建抽象策略类让具体策略类继承3. 日志和异常处理在策略类中添加登录日志记录统一捕获异常并返回友好的错误信息Service public class PasswordLoginStrategy implements LoginStrategy { Override public String execute(MapString, Object params) { try { // 登录逻辑 } catch (Exception e) { log.error(用户名密码登录失败{}, e.getMessage()); throw new LoginException(登录失败请重试); // 自定义业务异常 } } }4. 配置化登录类型将支持的登录类型存储在配置文件中前端调用时先获取支持的登录类型列表避免硬编码九、总结设计模式让代码更有 尊严回顾三年前的面条代码再看现在的实现最大的感受是好的设计模式能让代码在需求变化面前保持优雅。工厂模式和策略模式的组合就像给登录模块装了一个 热插拔 接口新增功能时不用改核心逻辑只需要添加新的 插件。最后送大家一句口诀登录逻辑别硬刚策略模式来帮忙工厂负责创实例开闭原则记心上Spring Boot 搭舞台依赖注入真叫爽需求万变不用慌代码优雅没商量