想给大家分享一下设计模式的一些用法以及在项目中怎么运用。
设计模式是软件设计中常见问题的典型解决方案。 它们就像能根据需求进行调整的预制蓝图, 可用于解决代码中反复出现的设计问题。
今天就拿其中一个问题来分析,使用策略模式来解决问题,没有了解过策略模式或者长时间不用已经忘了策略模式的小伙伴先来简单了解一下策略模式吧。
什么是策略模式?
策略模式是一种行为型模式,它将对象和行为分开,将行为定义为 一个行为接口
和 具体行为的实现
。策略模式最大的特点是行为的变化,行为之间可以相互替换。每个if判断都可以理解为就是一个策略。本模式使得算法可独立于使用它的用户而变化。
简单理解就是,针对不同的场景,使用不同的策略进行处理。
策略模式结构
-
Strategy 接口定义了一个算法族,它们都实现了 behavior() 方法。
-
Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。
策略模式适用场景
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们 的行为,那么使用策略模式可以动态地让一个对象在许多行 为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 如果一个对象有很多的行为,如果不用恰当的模式,这些行 为就只好使用多重的条件选择语句来实现。
- 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。
生活中比较常见的应用模式有:
- 电商网站支付方式,一般分为银联、微信、支付宝,可以采用策略模式。
- 电商网站活动方式,一般分为满减送、限时折扣、包邮活动,拼团等可以采用策略模式。
简单示例
场景:最近太热了,想要降降温,有什么办法呢
首先,定义一个降温策略的接口
public interface CoolingStrategy {
/**
* 处理方式
*/
void handle();
}
定义3种降温策略;实现策略接口
public class IceCoolingStrategy implements CoolingStrategy {
@Override
public void handle() {
System.out.println("使用冰块降温");
}
}
public class FanCoolingStrategy implements CoolingStrategy {
@Override
public void handle() {
System.out.println("使用风扇降温");
}
}
public class AirConditionerCoolingStrategy implements CoolingStrategy {
@Override
public void handle() {
System.out.println("使用空调降温");
}
}
定义一个降温策略的上下文
public class CoolingStrategyContext {
private final CoolingStrategy strategy;
public CoolingStrategyContext(CoolingStrategy strategy) {
this.strategy = strategy;
}
public void coolingHandle() {
strategy.handle();
}
}
测试
public class Main {
public static void main(String[] args) {
CoolingStrategyContext context = new CoolingStrategyContext(new FanCoolingStrategy());
context.coolingHandle();
context = new CoolingStrategyContext(new AirConditionerCoolingStrategy());
context.coolingHandle();
context = new CoolingStrategyContext(new IceCoolingStrategy());
context.coolingHandle();
}
}
运行结果:
使用风扇降温
使用空调降温
使用冰块降温
以上就是一个策略模式的简单实现
我在项目中使用:
最近做的一个建材项目中就用到了策略模式,需求:在不同场景下需要不同的算法公式来计算材料价格 ;下面直接来看部分代码:
策略结构
定义接口(策略入口)
public interface IndexFormulaStrategy {
IndexMaterialsResp getPrice(IndexMaterialsResp indexMaterialsResp);
}
实现类 算法一
@Service("E=C*D-A*B")
public class Formula_1 implements IndexFormulaStrategy{
/**
*
* 价格计算
* @param indexMaterialsResp
* @return
*/
@Override
public IndexMaterialsResp getPrice(IndexMaterialsResp info) {
//修改为新d来计算
BigDecimal bigDecimal = info.getContentAdjust().multiply(info.getPriceAdjustment());
BigDecimal bigDecimal1 = info.getControlContent().multiply(info.getCompilePrice());
info.setCalPrice(bigDecimal.subtract(bigDecimal1));
return info;
}
}
实现类 算法二
*/
@Service("E=A*(D-B)/B")
public class Formula_10 implements IndexFormulaStrategy{
/**
* 单方增减价格计算
* @param indexMaterialsResp
* @return
*/
@Override
public IndexMaterialsResp getPrice(IndexMaterialsResp info) {
if (BigDecimal.ZERO.compareTo(info.getCompilePrice())!=0){
// d-b
BigDecimal subtract = info.getPriceAdjustment().subtract(info.getCompilePrice());
if (BigDecimal.ZERO.compareTo(subtract)!=0){
info.setCalPrice(info.getControlContent().multiply(subtract).divide(info.getCompilePrice(),5,BigDecimal.ROUND_HALF_UP));
}else {
info.setCalPrice(new BigDecimal(0));
}
}else {
info.setCalPrice(new BigDecimal(0));
}
return info;
}
}
调用方式
//判断公式名称
String formulaName ="E=C*D-A*B"
if (StringUtils.isNotEmpty()) {
// 根据公式类型获取对应的策略 bean 入参为公式名称
IndexFormulaStrategy formulaStrategy = applicationContext.getBean(formulaName , IndexFormulaStrategy.class);
//对象转换
IndexMaterialsResp indexMaterialsResp = new IndexMaterialsResp();
BeanUtils.copyProperties(indexMaterialsBase1,indexMaterialsResp);
// 调用getPrice 方法 获取价格
formulaStrategy.getPrice(indexMaterialsResp);
updateIndexMaterials.setCalPrice(indexMaterialsResp.getCalPrice());
}
}
总结
通过策略设计模式的使用可以把我们方法中的重复逻辑抽取出来,也可以用来优化大量的if else。在使用这样的设计模式后可以很好的满足隔离性与和扩展性,对于不断新增的需求也非常方便承接。
了解策略模式的优点和缺点,合理的使用策略模式,会让你的代码更加的整洁优雅。
结束语
突发奇想写了这篇博客,希望能够帮助到大家,给大家提供一些代码优化思路。如果对大家有帮助,请不要吝啬你的点赞,关注,你的点赞是我更新的动力,以后会给大家出更多干货内容。本人是一名99年码农,希望可以跟大家一块努力进步!!!
原创不易,转载说明出处!!!