策略模式-java实战
策略模式(Strategy Pattern)是一种行为型模式。它定义了一系列算法,并将每一个算法封装起来,使它们可以互换使用,算法的变化不会影响使用算法的用户。
使用场景
当一个系统中有许多类,它们之间的区别仅在于它们的行为时。
存在多种相似算法,使用条件语句(如if...else、switch...case)维护逻辑变化。
场景假设
存在一个功能页面,操作的功能需要按历史数据、实时数据、未来数据等时间条件实现。
此时,普通实现,就会存在大量的以下条件语句
if(date == 历史){
历史业务逻辑
}
if(date == 未来){
未来业务逻辑
}
if(date == 实时){
实时业务逻辑
}
如果,后续业务出现新的时间条件,就需要一直往后面叠加if条件,就会变的越来越长,慢慢就形成业内所说的屎山。
实现步骤
-
定义策略接口:所有策略类都将实现这个统一的接口。
-
实现具体策略类:每个策略类封装一个具体的算法或行为。
-
实现环境类:包含一个策略对象的引用,并通过该引用调用策略。
代码示例
-
定义通用返回vo
public class BaseVo { }
-
定义策略接口:
import com.example.service.strategy.vo.BaseVo; import java.util.List; public interface Strategy { List<Object> queryList(); }
-
定义具体返回对象
public class FutureVo extends BaseVo{ } public class HisVo extends BaseVo{ } public class RealtimeVo extends BaseVo{ }
-
定义具体策略
//策略枚举 import com.example.service.strategy.Future; import com.example.service.strategy.History; import com.example.service.strategy.Realtime; import com.example.service.strategy.Strategy; public enum Type { HIS("0", new History()), TIME("1",new Realtime()), FUTURE("2",new Future()) ; private final String key; private final Strategy strategy; Type(String s, Strategy strategy) { this.key= s; this.strategy= strategy; } public String getKey() { return key; } public Strategy getStrategy() { return strategy; } } // his import com.example.service.strategy.vo.BaseVo; import com.example.service.strategy.vo.HisVo; import java.util.Collections; import java.util.List; public class History implements Strategy { @Override public List<Object> queryList() { System.out.println("History"); return Collections.singletonList(new HisVo()); } } //future import com.example.service.strategy.vo.BaseVo; import com.example.service.strategy.vo.FutureVo; import java.util.Collections; import java.util.List; public class Future implements Strategy { @Override public List<Object> queryList(){ System.out.println("Future"); return Collections.singletonList(new FutureVo()); } } //real time import com.example.service.strategy.vo.BaseVo; import com.example.service.strategy.vo.RealtimeVo; import java.util.Collections; import java.util.List; public class Realtime implements Strategy { @Override public List<Object> queryList() { RealtimeVo realtimeVo = new RealtimeVo(); System.out.println("Realtime"); return Collections.singletonList(realtimeVo); } }
-
定义策略工具类
import com.example.service.strategy.enums.Type; import com.example.service.strategy.vo.BaseVo; import org.springframework.stereotype.Service; import java.util.List; @Service public class ClientContext { public List<Object> query(Type type){ return getStrategy(type).queryList(); } public Strategy getStrategy(Type type){ return type.getStrategy(); } }
-
测试类
import com.example.service.strategy.enums.Type; public class Test { public static void main(String[] args){ ClientContext contextClient = new ClientContext(); List<Object> hisVoList= contextClient.query(Type.HIS); List<Object> timeVoList=contextClient.query(Type.TIME); List<Object> futureVos= contextClient.query(Type.FUTURE); } }
-
结果
History Realtime Future
将策略交给spring容器管理的实现方式
差异主要是在工具类/环境类的实现,即策略的获取。
-
定义策略接口
import com.example.service.strategy.vo.BaseVo; import java.util.List; public interface Strategy { String getKey(); List<Object> queryList(); }
-
定义策略具体类
// 策略枚举类 public enum StrategyType { HIS("0"), TIME("1"), FUTURE("2") ; private final String key; StrategyType(String s) { this.key= s; } public String getKey() { return key; } } //策略类 //his import com.example.service.strategy.enums.StrategyType; import com.example.service.strategy.vo.BaseVo; import com.example.service.strategy.vo.HisVo; import java.util.Collections; import java.util.List; public class History implements Strategy { @Override public String getKey() { return StrategyType.HIS.getKey(); } @Override public List<Object> queryList() { System.out.println("History"); return Collections.singletonList(new HisVo()); } } //future import com.example.service.strategy.enums.StrategyType; import com.example.service.strategy.vo.BaseVo; import com.example.service.strategy.vo.FutureVo; import java.util.Collections; import java.util.List; public class Future implements Strategy { @Override public String getKey() { return StrategyType.FUTURE.getKey(); } @Override public List<Object> queryList(){ System.out.println("Future"); return Collections.singletonList(new FutureVo()); } } //real time import com.example.service.strategy.enums.StrategyType; import com.example.service.strategy.vo.BaseVo; import com.example.service.strategy.vo.RealtimeVo; import java.util.Collections; import java.util.List; public class Realtime implements Strategy { @Override public String getKey() { return StrategyType.TIME.getKey(); } @Override public List<Object> queryList() { RealtimeVo realtimeVo = new RealtimeVo(); System.out.println("Realtime"); return Collections.singletonList(realtimeVo); } }
-
定义策略上下文类
import com.example.service.strategy.enums.StrategyType; import com.example.service.strategy.vo.BaseVo; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.List; import java.util.Map; @Component public class SpringClientContext implements ApplicationContextAware { private final Map<String,Strategy> strategyMap = new HashMap<>(); public List<Object> query(StrategyType strategyType){ return getStrategy(strategyType).queryList(); } public Strategy getStrategy(StrategyType strategyType){ return strategyMap.get(strategyType.getKey()); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Map<String,Strategy> tmpMap = applicationContext.getBeansOfType(Strategy.class); tmpMap.values().forEach(strategy -> strategyMap.put(strategy.getKey(),strategy)); } }
springboot 自动注入策略类
/**
* Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
*/
@Resource
private Map<String, Strategy> StrategyMap;
@Resource
private List<Strategy> StrategyList;