在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
优点
- 算法可以自由切换。
- 避免使用多重条件判断。
- 扩展性良好。
缺点
- 策略类会增多。
- 所有策略类都需要对外暴露。
使用场景
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
一、实现方式
假设一个场景,我们在电商系统中,订单分为很多种,例如:普通订单,秒杀订单,拼团订单等等。我们需要创建一个订单的时候,由于订单的类型不同,我们需要根据订单的类型执行不同的业务逻辑。
- 1、订单类型枚举类
package com.asurplus.common.strategy; import lombok.AllArgsConstructor; import lombok.Getter; /** * 订单类型枚举类 */ @Getter @AllArgsConstructor public enum OrderTypeEnum { COMMON(1001, "普通订单"), SECKILL(1002, "秒杀订单"), SPELL(1003, "拼团订单"); int type; String desc; }
我们的订单分为三种,普通订单,秒杀订单,拼团订单。
- 2、订单处理接口
package com.asurplus.common.strategy; /** * 订单处理接口 */ public interface OrderService { /** * 创建订单 * * @return */ void createOrder(); /** * 获取订单类型 * * @return */ OrderTypeEnum type(); }
- 3、普通订单处理器
package com.asurplus.common.strategy; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * 普通订单处理器 */ @Slf4j @Service public class CommonOrderServiceImpl implements OrderService { @Override public void createOrder() { log.info("创建 普通订单"); } @Override public OrderTypeEnum type() { return OrderTypeEnum.COMMON; } }
- 4、秒杀订单处理器
package com.asurplus.common.strategy; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * 秒杀订单处理器 */ @Slf4j @Service public class SeckillOrderServiceImpl implements OrderService { @Override public void createOrder() { log.info("创建 秒杀订单"); } @Override public OrderTypeEnum type() { return OrderTypeEnum.SECKILL; } }
- 5、拼团订单处理器
package com.asurplus.common.strategy; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * 拼团订单处理器 */ @Slf4j @Service public class SpellOrderServiceImpl implements OrderService { @Override public void createOrder() { log.info("创建 拼团订单"); } @Override public OrderTypeEnum type() { return OrderTypeEnum.SPELL; } }
- 6、下单管理器
package com.asurplus.common.strategy; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; import java.util.Optional; /** * 订单管理器 */ @Component public class OrderManager { /** * Autowired 注解的强大之处 */ @Autowired private List<OrderService> orderServices; /** * 创建订单 * * @param type 订单类型 * @return */ public void createOrder(int type) { /** * 根据订单类型,找到对应的处理器 */ Optional<OrderService> any = orderServices.stream().filter(f -> f.type().getType() == type).findAny(); /** * 没有对应的处理器 */ if (!any.isPresent()) { throw new RuntimeException("没有找到相应的订单实现"); } // 创建订单 any.get().createOrder(); } }
这里就能体现出 @Autowired 的强大之处,可以一次性自动注入多个对象。根据订单类型,选出对应的处理器来处理该订单。
二、测试
- 1、引入依赖
<!-- 测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency>
- 2、测试用例
package com.asurplus.common.strategy; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; /** * 策略模式 */ @RunWith(SpringRunner.class) @SpringBootTest public class TestMain { @Autowired private OrderManager orderManager; @Test public void test() { // 创建 秒杀订单 orderManager.createOrder(OrderTypeEnum.SECKILL.getType()); } }
输出结果