策略模式定义:
定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
解决的问题:
在一些算法比较相似的情况下,需要有较多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 模块了。
}