策略模式
用策略模式代替If-else,主要是定义统一行为(接口或抽象类),并实现不同策略下的处理逻辑(对应实现类)。客户端使用时自己选择相应的处理类。
以订单为基础类
@Data
public class Order {
private String source;
private String payMethod;
private String code;
private BigDecimal amount;
public Order(String source, String payMethod, String code, BigDecimal amount) {
this.source = source;
this.payMethod = payMethod;
this.code = code;
this.amount = amount;
}
public Order() {
}
}
假如不同的订单来源,PC,移动端需要不同的处理逻辑。OrderService类处理时会用if-else对不同来源的订单做处理。
@Service
public class OrderService {
public void orderService(Order order) {
if(order.getSource().equals("pc")){
// 处理pc端订单的逻辑
}else if(order.getSource().equals("mobile")){
// 处理移动端订单的逻辑
}else {
// 其他逻辑
}
}
}
下面图解下吧
假如我们只针对不同来源的(pc,mobile)的订单,使用不同的处理器来处理。
随着业务扩展,我们可能需要手机微信支付,手机支付宝支付,PC微信支付,PC支付宝支付,这时我们只需要扩展OrderHandlerType注解接口即可
例如PcOrderHandler使用@OrderHandlerType时需要声明source=" ",payMethod=" "
定义注解类型
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface OrderHandlerType {
String source();
String payMethod();
}
定义OrderHandler接口
public interface OrderHandler {
void handle(Order order);
}
定义PC,手机不同处理器实现类
@OrderHandlerType(source = "pc",payMethod = "支付宝")
public class PcOrderHandler implements OrderHandler {
private Order o;
@Override
public void handle(Order order) {
System.out.println("pc端 支付宝方式 处理器 开始了");
}
public Order getO() {
return o;
}
public void setO(Order o) {
this.o = o;
}
}
@OrderHandlerType(source = "mobile",payMethod = "支付宝")
public class MobileOrderHandler implements OrderHandler {
@Override
public void handle(Order order) {
System.out.println("mobile 处理器 开始了");
}
}
定义OrderService
注入Map,用来存不同订单来源和不同支付方式的不同处器处理,Key:订单处理类型,Value:不同处理器处理
@Service
public class OrderService {
private Map<String,OrderHandler> orderHandlerMap;
private Map<OrderHandlerType,OrderHandler> orderHandlerMap2;
@Autowired
ApplicationContext context;
//注入Map容器,Key为订单来源,Value为订单处理器
@Autowired
public void setOrderHandlerMap(List<OrderHandler> orderHandlers){
//注入各种类型的订单处理类
// orderHandlerMap=orderHandlers.stream().collect(
// Collectors.toMap(orderHandler -> AnnotationUtils.findAnnotation(orderHandler.getClass(),OrderHandlerType.class).source(),v->v,(v1,v2)->v1));
orderHandlerMap = context.getBeansOfType(OrderHandler.class);
}
public void orderService(Order order){
OrderHandler orderHandler = orderHandlerMap.get(order.getSource());
orderHandler.handle(order);
}
//扩展功能:pc微信支付,pc支付宝支付,手机微信支付,手机支付宝支付
//注入Map容器,Key为订单处理类型,Value为订单处理器
@Autowired
public void setOrderHandlerMap2(List<OrderHandler> orderHandlers){
orderHandlerMap2=orderHandlers.stream().collect(
Collectors.toMap(orderHandler -> AnnotationUtils.findAnnotation(orderHandler.getClass(),OrderHandlerType.class),v->v,(v1,v2)->v1));
}
public void orderService2(Order order){
OrderHandlerTypeImpl orderHandlerType = new OrderHandlerTypeImpl(order.getSource(), order.getPayMethod());
OrderHandler orderHandler = orderHandlerMap2.get(orderHandlerType);
orderHandler.handle(order);
}
}
测试一下吧
@RunWith(SpringRunner.class)
@SpringBootTest(classes=IfelseApplication.class)
public class TestOrder {
@Autowired
private OrderService orderService;
@Test
public void test1(){
List<OrderHandler> orderHandlers=new ArrayList<>();
Order order = new Order("pc", "微信", "001", new BigDecimal(4000));
PcOrderHandler pcOrderHandler = new PcOrderHandler();
pcOrderHandler.setO(order);
orderHandlers.add(pcOrderHandler);
orderService.setOrderHandlerMap(orderHandlers);
orderService.orderService(order);
}
@Test
public void test2(){
List<OrderHandler> orderHandlers=new ArrayList<>();
Order order = new Order("pc", "支付宝", "002", new BigDecimal(8000));
PcOrderHandler pcOrderHandler = new PcOrderHandler();
pcOrderHandler.setO(order);
orderHandlers.add(pcOrderHandler);
orderService.setOrderHandlerMap2(orderHandlers);
orderService.orderService2(order);
}
}
2020-11-25 10:52:28.298 INFO 20700 --- [ main] com.springboot.ifelse.TestOrder : Starting TestOrder using Java 1.8.0_202 on admin with PID 20700 (started by admin in D:\Projects\ifelse)
2020-11-25 10:52:28.312 INFO 20700 --- [ main] com.springboot.ifelse.TestOrder : No active profile set, falling back to default profiles: default
2020-11-25 10:52:29.631 INFO 20700 --- [ main] com.springboot.ifelse.TestOrder : Started TestOrder in 2.05 seconds (JVM running for 3.924)
pc端 支付宝方式 处理器 开始了