一、策略模式概述:
策略模式(又叫政策Policy模式),属于对象行为模式下的:Strategy类提供了可插入式(Pluggable)算法的实现方案。
策略模式的定义-意图:定义一系列算法,将每一个算法封装起来,并让它们互相替换。策略模式让算法可以独立于使用它的客户变化。
二、模式策略的优缺点:
优点:
1.提供了对开闭(开时针对扩展功能是开放的,闭对修改功能是关闭的)原则的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为;
2.提供了管理相关的算法族的办法;
3.提供了一种可以替换继承关系的办法;
4.可以避免多重条件选择语句;
5.提供了一种算法的复用机制,不同环境类可以方便地复用策略类。(单一职责)
缺点:
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类; 2.将造成系统产生很多具体策略类; 3.无法同时在客户端使用多个策略类。
适用环境:
1.一种系统需要动态地在几种算法中选择一种; 2.避免使用难以维护的多重条件选择语句; 3.不希望客户端知道复杂的、与算法相关的数据结构,提高算法的保密性与安全。
四种不同的实现方式:
枚举类,方式一
@AllArgsConstructor
public enum TrafficCodeEmun {TRAIN("TRAIN","火车"),BUS("BUS","大巴");private final String code;private final String desc;
}
|
方式四,利用配置文件,保存读取配置文件的结果
@Configuration
public class TrafficType {@Value("#{${trafficType:{}}}")private Map<String, String> trafficType;@Beanpublic Map<String, String> getTrafficType() {return trafficType;}}#方式四,配置文件yml文件中的内容
trafficType: "{'train': 'trainModeServiceImpl','bus': 'busModeServiceImpl'
}"
|
核心工厂类
@Component
@Slf4j
public class TrafficModeFactory implements ApplicationContextAware {//保存实例化的策略类标识和策略类//方式一public static final ConcurrentHashMap<TrafficCodeEmun, TrafficModeService> TRAFFIC_BEAN_MAP = new ConcurrentHashMap<>();//方式二、方式三、方式四public static final ConcurrentHashMap<String, TrafficModeService> TRAFFIC_BEAN_MAP = new ConcurrentHashMap<>();//@AutowiredTrafficType trafficType;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {Map<String, TrafficModeService> map = applicationContext.getBeansOfType(TrafficModeService.class);//方式一和方式二map.forEach((key, value) -> TRAFFIC_BEAN_MAP.put(value.getCode(), value));//方式三map.forEach((key, value) -> TRAFFIC_BEAN_MAP.put(key, value));//方式四,只用这一句trafficType.getTrafficType().forEach((key, value) -> {TRAFFIC_BEAN_MAP.put(key, (TrafficModeService) applicationContext.getBean(value));});}//方式一public static <T extends TrafficModeService> T getTrafficMode(TrafficCodeEmun code) {return (T) TRAFFIC_BEAN_MAP.get(code);}//方式二、三、四public static <T extends TrafficModeService> T getTrafficMode(String code) {return (T) TRAFFIC_BEAN_MAP.get(code);}
}
|
策略接口,策略实现类
public interface TrafficModeService {/*** 查询交通方式编码标识* @return 编码*///方式一TrafficCodeEmun getCode();//方式二String getCode();//方式三、四,去掉getCode()方法/*** 获取交通方式的费用* @return 费用*/Integer getFee();}@Service
public class TrainModeServiceImpl implements TrafficModeService {/*** 获取交通方式编码标识* @return 编码*/@Overridepublic TrafficCodeEmun getCode() {//方式一,利用枚举类型return TrafficCodeEmun.TRAIN;}@Overridepublic String getCode() {//方式二,去掉不用枚举类型,直接设置返回值return "TRAIN";}//方式三、四,直接去掉getCode()方法和枚举类型/*** 获取交通方式的费用* @return 费用*/@Overridepublic Integer getFee() {return 5000;}}@Service
public class BusModeServiceImpl implements TrafficModeService {/*** 查询交通方式编码* @return 编码*/@Overridepublic String getCode() {return "bus";}/*** 查询交通方式的费用,单位:分* @return 费用*/@Overridepublic Integer getFee() {return 6000;}}//测试类
@Test
public void testParttern() {//方式一Integer fee = TrafficModeFactory.getTrafficMode(TrafficCodeEmun.TRAIN).getFee();//方式二Integer fee = TrafficModeFactory.getTrafficMode("train").getFee();//方式三Integer fee = TrafficModeFactory.getTrafficMode("trainModeServiceImpl").getFee();//方式四Integer fee = TrafficModeFactory.getTrafficMode("train").getFee();System.out.println(fee);
}
|
策略模式,本身就是要求使用者知道都有哪些策略类才行,扩展时可通过抽象类实现策略接口,然后策略类继承抽象类
方式一:有枚举类,新增一种出行方式需要增加一个策略类,修改枚举类型
方式二:没有枚举类,新增一种出行方式,只需增加一个策略类,设置名称标识,不需要枚举类型,也不需要修改枚举类型
方式三:没有枚举类,新增一种出行方式,只需增加一个策略类,只是传参的时候需要传策略实现类在spring容器中的标识
方式四:没有枚举类,但是使用了配置文件,新增一种出行方式,只需增加一个策略类,以及在配置文件中增加内容即可
增加枚举类也可以达到无侵入业务代码