工厂模式是解耦对象的创建和使用,观察者模式是解耦观察者和被观察者。策略模式跟两者类似,也能起到解耦的作用,解耦的是策略的定义、创建、使用这三部分。
通常的使用方式
**
**
一个策略接口和一组实现这个接口的策略类。因为所有的策略类都实现相同的接口,所以,客户端代码基于接口而非实现编程,可以灵活地替换不同的策略。
public interface Strategy { void algorithm(); } public class StrategyA implements Strategy { @Override public void algorithm() { //具体的算法... } } public class StrategyB implements Strategy { @Override public void algorithm() { //具体的算法... } }
2.策略创建
一组策略,使用时一般通过type来判断创建哪个策略。
工厂封装创建逻辑,对客户端屏蔽创建细节
public class StrategyFactory { private static final Mapstrategies = new HashMap<>(); static { strategies.put("A", new StrategyA()); strategies.put("B", new StrategyB()); } public static Strategy getStrategy(String type) { if (type == null || type.isEmpty()) { throw new IllegalArgumentException("type should not be empty."); } return strategies.get(type); } }
如果策略类是无状态的,不包含成员变量,只是纯粹的算法实现,这样的策略对象是可以被共享使用的,使用map缓存
如果策略类是有状态的,根据业务场景的需要,我们希望每次从工厂方法中,获得的都是新创建的策略对象,而不是缓存好可共享的策略对象,则:
public class StrategyFactory { public static Strategy getStrategy(String type) { if (type == null || type.isEmpty()) { throw new IllegalArgumentException("type should not be empty."); } if (type.equals("A")) { return new StrategyA(); } else if (type.equals("B")) { return new StrategyB(); } return null; } }
3.策略的使用
最常见的是运行时动态确定使用哪种策略,这也是策略模式最典型的应用场景。
Strategy strategy=StrategyFactory.getStrategy(type)
简便的使用方式
1.策略定义
public interface Strategy { //用来匹配策略 boolean match(String type); String algorithm(); } public class StrategyA implements Strategy { @Override public boolean match(String type) { return "A".equals(type); } @Override public String algorithm() { //具体的算法... return "this is A"; } } public class StrategyB implements Strategy { @Override public boolean match(String type) { return "B".equals(type); } @Override public String algorithm() { //具体的算法... return "this is B"; } } //默认执行的策略 public class DefaultStrategy implements Strategy { @Override public boolean match(String type) { return false; } @Override public String algorithm() { return "this is 默认方法"; } }
2.策略使用
@Autowired private ListstrategyList; @Autowired private DefaultStrategy defaultStrategy; @Test public void test_Strategy(){ String type="A"; //直接使用lamba表达式,match匹配执行Strategy String result=strategyList.stream() .filter(strategy -> strategy.match(type)) .findFirst() .orElse(defaultStrategy) .algorithm(); } 输出result="this is A";
实战代码优化
原代码写法
if (TradeChannelTypeEnum.RAPID_SEND.getType() == tradeChannel) { result = rapidSendInvSaleMatch.match(dbEntity, EnumsMatchType.NORMAL.getType(), tradeChannel..); } else if (TradeChannelTypeEnum.FLASH_SEND.getType() == tradeChannel) { result = flashSendInvSaleMatch.match(dbEntity, EnumsMatchType.NORMAL.getType(), tradeChannel..); } else if (TradeChannelTypeEnum.BRAND_OFFER.getType() == tradeChannel) { result = brandOfferInvSaleMatch.match(dbEntity, EnumsMatchType.NORMAL.getType(), tradeChannel..); } else { result = defaultInvSaleMatch.match(dbEntity, EnumsMatchType.NORMAL.getType(), tradeChannel..); }
可以看出,在业务增加的情况下,不断增加if-else,增加 InvSaleMatch service。根据不同的tradeChannel选择不同的 **InvSaleMatch (**InvSaleMatch都继承自AbsInvSaleMatch),可直接使用策略模式。
优化之后
//AbsInvSaleMatch增加 tradeChannelMatch方法 boolean tradeChannelMatch(int tradeChannel); //各个InvSaleMatch 实现类里判断tradeChannel,用来替代之前代码里的if判断
@Autowired private List saleMatchList; result = saleMatchList.stream().filter(hander -> hander.tradeChannelMatch(tradeChannel)).findFirst() .orElse(defaultInvSaleMatch) .match(dbEntity, EnumsMatchType.NORMAL, tradeChannel..);
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)