Java策略模式讲解以及示例

策略模式(Strategy Patten)

什么是策略模式?

比如对象的某个行为,在不同场景有不同实现方式,可以将这些行为的具体实现定义为一组策略,每个实现类实现种策略,在不同场景使用不同的实现,并且可以自由切换策略。

策略模式结构图如下

请添加图片描述

策略模式需要一个策略接口,不同的策略实现不同的实现类,在具体业务环境中仅持有该策略接口,根据不同的场景使用不同的实现类即可。

面向接口编程,而不是面向实现。

策略模式的优点

1、干掉繁琐的 if、switch 判断逻辑;

2、代码优雅、可复用、可读性好;

3、符合开闭原则,扩展性好、便于维护;

策略模式的缺点

1、策略如果很多的话,会造成策略类膨胀;

2、使用者必须清楚所有的策略类及其用途;

策略模式示例

做个例子:比如去服装店买衣服,普通会员不打折,黄金会员打9折,铂金会员打8折,钻石会员打7折,这样不同的客户价格计算方式不同,这个时候就可以使用策略模式。

/**
 * @author XQ0136
 * @description 账单接口
 * @date 2022/6/21 11:48
 */
public interface IBill {

	/**
	 * 计算账单
	 * @param money
	 * @return 应付金额
	 */
	BigDecimal calculate(BigDecimal money);
}

普通会员实现:
/**
 * @author XQ0136
 * @description 普通会员
 * @date 2022/6/21 11:57
 */
@Service("RegularType")
public class RegularMember implements IBill{

	@Override
	public BigDecimal calculateBill(BigDecimal money) {

		//10折
		return money.multiply(new BigDecimal(1));
	}
}
黄金会员:
/**
 * @author XQ0136
 * @description 黄金会员
 * @date 2022/6/21 11:57
 */
@Service("GoldType")
public class GoldMember implements IBill{

	@Override
	public BigDecimal calculateBill(BigDecimal money) {
		//9折
		return money.multiply(new BigDecimal(0.9)).setScale(2, RoundingMode.HALF_UP);
	}
}

铂金会员实现:
/**
 * @author XQ0136
 * @description 铂金会员
 * @date 2022/6/21 11:57
 */
@Service("PlatinumType")
public class PlatinumMember implements IBill{

	@Override
	public BigDecimal calculateBill(BigDecimal money) {
		//8折
		return money.multiply(new BigDecimal(0.8)).setScale(2, RoundingMode.HALF_UP);
	}
}

钻石会员实现:

/**
 * @author XQ0136
 * @description 钻石会员
 * @date 2022/6/21 11:57
 */
@Service("DiamondType")
public class DiamondMember implements IBill{

	@Override
	public BigDecimal calculateBill(BigDecimal money) {
		//7折
		return money.multiply(new BigDecimal(0.7)).setScale(2, RoundingMode.HALF_UP);
	}
}

这里将Bean添加到Spring容器中管理了,不用自己去new对象,或者使用工厂模式和策略模式结合使用。

测试接口:
@RestController
public class IBillStrategyContext {


	@Autowired
	private ApplicationContext applicationContext;

	/**
	 * 计算账单
	 * @param memberType
	 * @param money
	 * @return 应付金额
	 */
	@GetMapping("calculate")
	public BigDecimal calculateBill(@RequestParam("memberType") String memberType,
									@RequestParam("money") BigDecimal money){

		IBill bean = applicationContext.getBean(memberType, IBill.class);
		return bean.calculateBill(money);
	}

}
测试:

http://localhost:10401/calculate?memberType=GoldType&money=1000

请添加图片描述

http://localhost:10401/calculate?memberType=DiamondType&money=1000

请添加图片描述

Jdk 中策略模式的应用:

1、线程池中的拒绝策略

线程池的构造中有一个拒绝策略参数,默认是默认拒绝策略:

请添加图片描述

其实这就是一个策略接口
请添加图片描述

下面有几种拒绝策略的实现

请添加图片描述

在创建线程池的时候,就可以传入不同的拒绝策略,这就是 JDK 中策略模式的经典实现了。

2、比较器

JDK 中大量使用了 Comparator 这个策略接口:

请添加图片描述

策略接口有了,但策略需要开发人员自己定。

集合排序我们比较熟悉的了,不同的排序规则其实就是不同的策略:
请添加图片描述

这个策略模式使用了函数式编程接口,比较规则使用匿名内部类或者 Lambda 表达式就搞定了,不需要每个规则定义一个实现类,这样就大量省略策略类了。

这个策略模式可能藏的比较深,但也是 JDK 中经典的策略模式的应用了。

总结

策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者。

参考文章:https://blog.csdn.net/youanyyou/article/details/116931663

  • 14
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值