一、引言
在程序执行过程中往往有多需要进行if-else判断的情况,通过使用策略模式可以解决在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
本文主要讲解通过使用自定义注解的方式来实现策略模式。
二、实现方式
1、本文以常见的订单处理为例。首先定义一个订单实体类。
package com.example.demo.strategy;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
/**
* 订单来源
*/
private String source;
}
2、定义一个OrderHandlerInterface接口,此接口规定了处理订单的方法。
package com.example.demo.strategy;
/**
* 订单接口
*/
public interface OrderHandlerInterface {
void doOrder();
}
3、定义一个自定义注解类OrderHandlerType,来表示某个类是用来处理何种来源的订单。
package com.example.demo.strategy;
import org.springframework.stereotype.Service;
import java.lang.annotation.*;
/**
* 自定义注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface OrderHandlerType {
String type();
}
4、针对不同来源的订单实现类,下面两个实现类分别表示来源于pc端和phone端执行不同的处理逻辑。
@OrderHandlerType(type = "pc")
public class OrderHandlerImpl implements OrderHandlerInterface{
@Override
public void doOrder() {
System.err.println("执行pc端");
}
}
@OrderHandlerType(type = "phone")
public class OrderHandlerImpl2 implements OrderHandlerInterface{
@Override
public void doOrder() {
System.err.println("执行phone端");
}
}
5、以上准备就绪后,就是向spring容器中注入各种订单处理的handler,并在OrderService.orderService方法中,通过策略(订单来源)去决定选择哪一个OrderHandlerInterface去处理订单。我们可以这样做:
package com.example.demo.strategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 向spring容器中注入各种订单处理的handler
*/
@Service
public class OrderService {
private Map<String, OrderHandlerInterface> orderHandlerInterfaceMap;
@Autowired
public void setReportTaskBusinessLogicMap(List<OrderHandlerInterface> orderHandlerInterfaces) {
orderHandlerInterfaceMap = orderHandlerInterfaces.stream().collect(
Collectors.toMap(t -> AnnotationUtils.findAnnotation(t.getClass(), OrderHandlerType.class).type(),
v -> v, (v1, v2) -> v1));
}
public void orderService(List<Order> order){
order.forEach(t->{
//可以根据注解的值判断走哪个实现类,如果有多个实现类就会依次走
OrderHandlerInterface orderHandlerInterface = orderHandlerInterfaceMap.get(t.getSource());
orderHandlerInterface.doOrder();
});
}
}
通过上述步骤之后,通过自定义注解实现的策略模式就已完成。接下来测试一下
@Autowired
private OrderService orderService;
@Test
void test(){
Order pc = new Order("pc");
Order windows = new Order("phone");
orderService.orderService(Arrays.asList(pc,windows));
}
执行结果:
此时通过实现订单的接口并加上自定义注解,根据传入的注解值就可以决定动态执行哪些实现类了。