工厂+策略模式

一、策略模式概述:

策略模式(又叫政策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;

    @Bean
    public 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<>();
  
  	//@Autowired
    TrafficType trafficType;
 
    @Override
    public 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 编码
     */
    @Override
    public TrafficCodeEmun getCode() {
      	//方式一,利用枚举类型
        return TrafficCodeEmun.TRAIN;
    }
  
  	@Override
    public String getCode() {
      	//方式二,去掉不用枚举类型,直接设置返回值
      	return "TRAIN";
    }
  
  	//方式三、四,直接去掉getCode()方法和枚举类型
  
 
    /**
     * 获取交通方式的费用
     * @return 费用
     */
    @Override
    public Integer getFee() {
        return 5000;
    }
 
}


@Service
public class BusModeServiceImpl implements TrafficModeService {

    /**
     * 查询交通方式编码
     * @return 编码
     */
    @Override
    public String getCode() {
        return "bus";
    }

    /**
     * 查询交通方式的费用,单位:分
     * @return 费用
     */
    @Override
    public 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容器中的标识

方式四:没有枚举类,但是使用了配置文件,新增一种出行方式,只需增加一个策略类,以及在配置文件中增加内容即可

增加枚举类也可以达到无侵入业务代码

posted @   complexlong  阅读(179)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示