一、什么是策略模式?
策略模式主要针对的是一组算法,将每一种算法封装到共同接口的独立类中,从而使他们可以相互替换。他的最大的特点是使得算法可以在不影响客户端情况下发生变化,从而改变不同的功能。
二、策略模式的优缺点?
优点:可以避免使用多重条件(if-else)语句,解决多重判断的不易维护,提高扩展性,维护性增强,代码的可读性增强。并且,如果算法的某些逻辑相同,还能够放入父类中,从而避免代码重复。
缺点:后期维护不同的策略类是非常多、定义类比较多,代码量增大。
三、策略模式的场景?
我们为什么要使用策略模式,相信大家都遇到过这样一个场景。会员大家都了解,有普通会员,有白银会员,有黄金会员,还有钻石会员,成为了不同的会员,我们就可以享受不同的待遇,不然我们干嘛要不是花钱就花时间的去成为更高的会员嘛。那么,对于不同的会员待遇,我们在这里首先谈论一点,那就是可以享受优惠,进行打折服务。比如普通会员不打折,白银会员打九折,黄金会员打八折,钻石会员打七折。对于这种逻辑,我们很容易想到使用多个if进行判断。那么,这就带来了代码可读性差,还有最大的问题就是扩展性差。并且所有的判断都在一个方法内,造成了一个该方法的代码量庞大。
1.折扣活动;2.会员折扣;3.支付接口调用;
快速排序、冒泡排序、选择排序
四、策略模式?
抽象策略角色:策略类,通常由一个接口或者抽象类实现。
具体策略角色:包装了相关的算法和行为。
环境角色:持有一个策略类的引用,最终给客户端调用。
五、代码实现?
1.首先创建会员策略
/** * @Description: 会员策略 * @Author: HuangChangJun * @Date: 2019/5/8 9:11 * @Version: 1.0 */ public interface MemberStrategy { /* * 实现会员优惠的算法 * */ String memberFavourable(); }
2.实现两种会员优惠策略
/** * @Description: 黄金会员优惠接口实现 * @Author: HuangChangJun * @Date: 2019/5/8 9:29 * @Version: 1.0 */ @Component public class MemberVipStrategy implements MemberStrategy { @Override public String memberFavourable() { return "黄金会员优惠接口。。。"; } }
/** * @Description: 白银会员优惠接口实现 * @Author: HuangChangJun * @Date: 2019/5/8 9:30 * @Version: 1.0 */ @Component public class MemberSilverStrategy implements MemberStrategy { @Override public String memberFavourable() { return "白银会员优惠接口调用。。。。"; } }
3.创建会员实体类
/** * @Description: 用户 * @Author: HuangChangJun * @Date: 2019/5/8 9:06 * @Version: 1.0 */ @Data //说明一下,@Data使用的是lombok方式来创建get、set,如果没有引入的,可以直接使用封装,效果是一样的 public class User { //用户ID private String uId; //用户姓名 private String uName; //用户密码 private String uPassword; //用户等级 private String uLevel; //用户策略ID private String uStrategyBeanId; }
4.创建会员数据访问层
/** * @Description: 用户数据访问 * @Author: HuangChangJun * @Date: 2019/5/8 9:32 * @Version: 1.0 */ public interface UserMapper { @Select("select u_id as uId,u_name as uName,u_password as uPassword,u_level as uLevel,u_strategy_bean_id as uStrategyBeanId\n"+ " from `user` where u_level = #{uLevel}") public User getUser(String uLevel); }
5.创建springUtils工具类
/** * @Description: * @Author: HuangChangJun * @Date: 2019/5/7 23:29 * @Version: 1.0 */ @Component public class SpringUtils implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } //获取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } //通过name获取 Bean. public static Object getBean(String name){ return getApplicationContext().getBean(name); } //通过class获取Bean. public static <T> T getBean(Class<T> clazz){ return getApplicationContext().getBean(clazz); } //通过name,以及Clazz返回指定的Bean public static <T> T getBean(String name,Class<T> clazz){ return getApplicationContext().getBean(name, clazz); } }
6.创建上下文
/** * @Description: 会员上下文策略 * @Author: HuangChangJun * @Date: 2019/5/8 9:33 * @Version: 1.0 */ @Component public class MemberContextStrategy { @Autowired private UserMapper userMapper; public String memberPay(String level){ //1.通过会员类型查找到BeanId User user=userMapper.getUser(level); if (user==null){ return "没有该等级"; } //2.从Spring容器中获得实例对象 String strategyBeanId=user.getUStrategyBeanId(); if (strategyBeanId==null){ return "没有对该会员进行策略配置"; } MemberStrategy memberStrategy=SpringUtils.getBean(strategyBeanId, MemberStrategy.class); //3.调用对象的方法 return memberStrategy.memberFavourable(); } }
7. 创建访问
/** * @Description: 会员策略控制器 * @Author: HuangChangJun * @Date: 2019/5/8 9:40 * @Version: 1.0 */ @RestController public class MemberStrategyController { @Autowired private MemberContextStrategy memberContextStrategy; @RequestMapping("memberFavourable") public String memberStrategy(String level){ return memberContextStrategy.memberPay(level); } }
8.由于我的项目使用的是SpringBoot,创建SpringBoot的启动文件
/** * @Description: * @Author: HuangChangJun * @Date: 2019/5/7 23:37 * @Version: 1.0 */ @SpringBootApplication @MapperScan("com.hcj.mapper") public class StrategySpringBoot { public static void main(String[] args) { SpringApplication.run(StrategySpringBoot.class); } }
9.效果展示图
六、总结?
个人觉得,策略模式学习起来还是挺简单的,但这只是表层的东西,还有更深层次的东西需要我们去挖掘。对于我目前的工作中,真的还没有遇到过这种场景,学完这个之后,我觉得以后遇到需要做选择题的时候,就可以使用这种设计模式。