电子商务网站设计规划书,赣州网站建设公司哪家好,永州建设网站公司,网站建站建设首选上海黔文信息科技有限公司2优雅实现策略器模式 场景废话少说#xff0c;源码地址。讲解关于本文创建登陆策略创建环境#xff08;注册器#xff09;简化代码 创建父类对象#xff0c;也方便后期扩展 具体策略实现类用户名密码登陆手机号登陆 触发点调试简言 场景
登陆场景使用#xff08;登陆之后返… 优雅实现策略器模式 场景废话少说源码地址。讲解关于本文创建登陆策略创建环境注册器简化代码 创建父类对象也方便后期扩展 具体策略实现类用户名密码登陆手机号登陆 触发点调试简言 场景
登陆场景使用登陆之后返回用户信息和token所做操作基本一致杜绝多个判断
用户名密码登陆指纹登录手机号登陆 楼主之前写过一次通过注解实现的那个看起来没有注册器实现优雅。 策略器可以使用的场景很多主要为了杜绝多if判断把if判断需实现的信息放在自己的实现类中提升代码可阅读性提高执行效率降低出错概率。 八股文可扩展性高灵活性高代码复用性高单一职责原则可替换性高。
废话少说源码地址。
代码地址
git clone https://github.com/gwy572294624/strategy-demo-new
讲解
chatGpt关于策略模式的八股文 策略模式Strategy Pattern是一种行为型设计模式用于将不同的算法封装成独立的策略类并使这些策略类可以相互替换以实现在运行时动态地选择不同的算法。
在策略模式中有三个主要的角色 环境Context环境类是策略模式的核心其内部持有一个策略对象的引用。环境类将具体的任务委派给策略对象进行处理而不直接实现具体的算法逻辑。 策略Strategy策略类是一个接口或抽象类它定义了具体算法的方法。不同的策略类实现了不同的算法逻辑。策略类之间可以相互替换提供了算法的灵活配置。 具体策略Concrete Strategies具体策略类是策略模式的实现类实现了策略接口或抽象类中定义的具体算法逻辑。
策略模式的工作流程如下 客户端创建一个环境对象并通过构造函数或设置方法将具体的策略对象传递给环境对象。 客户端根据需求选择合适的策略对象。 环境对象在执行任务时会将具体的算法委派给当前持有的策略对象进行处理。 当需要切换算法时客户端可以动态地替换环境对象的策略对象实现不同的算法逻辑。
策略模式的优点包括灵活性、可替换性、可扩展性和代码复用性。它可以避免使用大量的条件语句或开关语句将不同的算法逻辑封装在独立的策略类中使系统更加灵活、易于扩展和维护。
关于本文
策略模式组成是通过环境策略具体实现三部分组成本文将环境context通过注册器实现实现自动化注入容器中维护起来更方便。主要用于优化系统中多if判断场景大一点的系统应该都能碰到所以希望可以帮助到大家。
创建登陆策略 public interface LoginStrategy {/*** 检查参数* return*/default Result checkParam(LoginPatamDTO loginPatamDTO){return Result.err();}/*** 登陆* param loginPatamDTO* return*/default ResultLoginUserInfoVO login(LoginPatamDTO loginPatamDTO){return Result.err();}
}
创建环境注册器
将bean对象放在指定的map容器中。 Component
public class LoginCommonStrategyRegistry {Autowiredprivate BeanFactory beanFactory;private MapLoginTypeEnum, LoginStrategy loginrCommonStrategyMap new ConcurrentHashMap();public MapLoginTypeEnum, LoginStrategy mapGet() {return this.loginrCommonStrategyMap;}/*** 初始化策略*/public void registry(LoginTypeEnum loginTypeEnum, Class glass) {LoginStrategy funderCommonStrategy (LoginStrategy)beanFactory.getBean(glass);this.loginrCommonStrategyMap.put(loginTypeEnum, funderCommonStrategy);}
}
简化代码 创建父类对象也方便后期扩展
PostConstruct 是 Java 中的一个注解用于标记一个方法在对象创建之后通过构造函数创建并注入依赖后在依赖注入完成之后立即执行。它的作用是在对象初始化阶段执行一些必要的操作例如初始化资源、建立连接、加载数据等。 Service
public abstract class AbstractLoginService implements LoginStrategy {private final LoginCommonStrategyRegistry loginCommonStrategyRegistry;public AbstractLoginService(LoginCommonStrategyRegistry loginCommonStrategyRegistry){this.loginCommonStrategyRegistry loginCommonStrategyRegistry;}/*** 注册当前类到策略map中*/PostConstructprotected abstract void initRegistry();
}
具体策略实现类
用户名密码登陆 Service
Slf4j
public class UserNameLoginService extends AbstractLoginService {public UserNameLoginService(LoginCommonStrategyRegistry loginCommonStrategyRegistry) {super(loginCommonStrategyRegistry);}Overrideprotected void initRegistry() {super.loginCommonStrategyRegistry.registry(LoginTypeEnum.USERNAME_TYPE, this.getClass());}Overridepublic Result checkParam(LoginPatamDTO loginPatamDTO) {if (ObjectUtils.isEmpty(loginPatamDTO.getUserName())) {return Result.err(用户名不能为空);}if (ObjectUtils.isEmpty(loginPatamDTO.getPassword())) {return Result.err(密码不能为空);}return Result.suc();}Overridepublic ResultLoginUserInfoVO login(LoginPatamDTO loginPatamDTO) {log.info(这里是用户名和密码登陆);if (loginPatamDTO.getUserName().equals(admin) loginPatamDTO.getPassword().equals(admin)) {// 创建默认对象 模拟登陆返回LoginUserInfoVO loginUserInfoVO LoginUserInfoVO.loginUserInfoVOCreate(loginPatamDTO.getLoginTypeEnum());return Result.suc(loginUserInfoVO);} else {return Result.err(用户名或者密码不正确);}}
}
手机号登陆 Service
Slf4j
public class PhoneLoginService extends AbstractLoginService {public PhoneLoginService(LoginCommonStrategyRegistry loginCommonStrategyRegistry) {super(loginCommonStrategyRegistry);}Overrideprotected void initRegistry() {super.loginCommonStrategyRegistry.registry(LoginTypeEnum.PHONE_TYPE, this.getClass());}Overridepublic Result checkParam(LoginPatamDTO loginPatamDTO) {if (ObjectUtils.isEmpty(loginPatamDTO.getPhone())) {return Result.err(手机号不能为空);}if (ObjectUtils.isEmpty(loginPatamDTO.getSmsCode())) {return Result.err(验证码不能为空);}return Result.suc();}Overridepublic ResultLoginUserInfoVO login(LoginPatamDTO loginPatamDTO) {log.info(这里是手机号登陆);if (loginPatamDTO.getPhone().equals(17777777777) loginPatamDTO.getSmsCode().equals(7777)) {// 创建默认对象 模拟登陆返回LoginUserInfoVO loginUserInfoVO LoginUserInfoVO.loginUserInfoVOCreate(loginPatamDTO.getLoginTypeEnum());return Result.suc(loginUserInfoVO);} else {return Result.err(验证码不正确);}}
}
触发点
如果没有写策略模式 那代码应该是这样
if(type.equals(用户名登陆)){// 用户名密码登陆验证
}else if(type.equals(手机号登陆)){// 手机号登陆
}else if(.......){....
}使用策略模式触发点确实简化了不少代码让代码优雅起来了。后续扩展啥的都很方便。
RestController
public class LoginController {/*** 模拟redis*/public static MapString, String userInforedis new ConcurrentHashMap();private final LoginCommonStrategyRegistry loginCommonStrategyRegistry;public LoginController(LoginCommonStrategyRegistry loginCommonStrategyRegistry) {this.loginCommonStrategyRegistry loginCommonStrategyRegistry;}RequestMapping(value /a/login)public ResultLoginUserInfoVO login(LoginPatamDTO loginPatamDTO) {if (ObjectUtils.isEmpty(loginPatamDTO.getLoginTypeEnum())) {return Result.err(无效的登陆方式);}LoginStrategy loginStrategy loginCommonStrategyRegistry.mapGet().get(loginPatamDTO.getLoginTypeEnum());if (loginStrategy null) {return Result.err(无效的登陆方式);}Result result loginStrategy.checkParam(loginPatamDTO);if (result.getCode() 0) {return result;}ResultLoginUserInfoVO login loginStrategy.login(loginPatamDTO);if (login.getCode() 1) {userInforedis.put(login.getDate().getToken(), JSON.toJSONString(login.getDate()));}return login;}}
调试
http://127.0.0.1:8080/a/login?loginTypeEnumUSERNAME_TYPEuserNameadminpasswordadmin{code:1,msg:成功,date:{token:57a44abe-e731-40f1-a9f6-1069710ac6fa,userInfoBO:{userId:这个是id,userRealName:这个是名字,userSex:这个是性别,userDeptIds:这个是部门,loginTypeEnum:USERNAME_TYPE}}}简言
在接入策略模式前一定要想好调用交互逻辑如果系统有现成的最好使用现成的。当然也要避免循环依赖注入。
希望本文可以帮到大家。