策略模式定義:
定義了算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。
解決的問題:
在一些算法比較相似的情況下,需要有較多if...else 或者switch case的時候,代碼比較複雜並且難以維護。
工作中的業務需求:
實現直播勳章系統時,涉及到每個區域(評論區,連麥區,房主區,進場特效區域)的勳章展示邏輯不一樣。一開始,使用switch...case...處理每個區域的邏輯,感覺代碼比較複雜。後來,把每個區域抽象成一個類,把每個區域的處理邏輯交給對應的類去處理。基於spring框架的ApplicationContextAware接口,使用策略模式實現了該業務邏輯。一下是demo:
1)創建勳章區域枚舉:
public enum MedalRegionEnum{
OWNER_REGION_MEDAL(1,"房主區域"),
AUDIENCE_REGION_MEDAL(2,"觀衆席區域"),
ENTER_SPECIAL_REGION_MEDAL(3,"進場特效區域"),;
MedalRegionEnum(int index, String desc) { this.index = index; this.desc = desc; }
private int index; private String desc;
public int getIndex() { return index; }
public String getDesc() { return desc; }
}
2)創建勳章區域服務接口。
public interface IMedalRegionService { //過濾以及排序勳章服務 List<MedalPO> filterAndSortMedals(List<MedalPO> list); //對應區域枚舉 MedalRegionEnum getRegionEnum(); }
3)創建一個抽象類,一個過濾勳章的虛函數,一個排序勳章的函數
public abstract class AbstractRegionService implements IMedalRegionService {
abstract List<MedalPO> filterMedals(List<MedalPO> medalPOList);
List<MedalPO> sortMedals(List<MedalPO> medalPOList){
//sort medalPOList
}
}
4)創建每個區域具體的勳章服務(RegionAudienceServiceImpl,RegionOwnerServiceImpl,RegionEnterServiceImpl),
繼承AbstractRegionService服務。
eg:
@Service
public class RegionOwnerServiceImpl extends AbstractRegionService {
List<MedalPO> filterMedals(List<MedalPO> medalPOList){
//doSomething 房主區域勳章的具體排序
}
@Override
public MedalRegionEnum getRegionEnum()
{ return MedalRegionEnum.OWNER_REGION_MEDAL; }
}
6)創建需要用勳章服務
@Service
public class MedalServiceImpl implements IMedalService, ApplicationContextAware {
private Map<MedalRegionEnum, IMedalRegionService> regionServiceMap = new ConcurrentHashMap<>();
//setApplicationContext方法初始化regionServiceMap
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, IMedalRegionService> regionTempMap = applicationContext.getBeansOfType(IMedalRegionService.class); regionTempMap.values().forEach(iMedalRegionService -> regionServiceMap.put(iMedalRegionService.getRegionEnum(), iMedalRegionService)); }
//接着可以用regionServiceMap替換可惡的if...else/switch ..case 模塊了。
}