设计模式之策略模式

一、什么是策略模式?

策略模式主要针对的是一组算法,将每一种算法封装到共同接口的独立类中,从而使他们可以相互替换。他的最大的特点是使得算法可以在不影响客户端情况下发生变化,从而改变不同的功能。

二、策略模式的优缺点?

优点:可以避免使用多重条件(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.效果展示图

六、总结?

个人觉得,策略模式学习起来还是挺简单的,但这只是表层的东西,还有更深层次的东西需要我们去挖掘。对于我目前的工作中,真的还没有遇到过这种场景,学完这个之后,我觉得以后遇到需要做选择题的时候,就可以使用这种设计模式。

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值