注解实现
假如对于不同来源(pc端、移动端)的订单需要不同的逻辑处理。项目中一般会有OrderService这样一个类,如下,里面有一坨if-else的逻辑,目的是根据订单的来源的做不同的处理。
策略模式就是要干掉上面的一坨if-else,使得代码看起来优雅且高大上。现在就让我们开始干掉这一坨if-else。话不多说,还是以最常 见的订单处理为例。首先定义这样一个订单实体类
@Data
public class Order {
/**
* 订单来源
*/
private String source;
/**
* 支付方式
*/
private String payMethod;
// ...其他的一些字段
}
1.首先定义一个OrderHandler接口,此接口规定了处理订单的方法。
public interface OrderHandler {
void handle(Order order);
}
2.实现OrderHandler接口。
public class OrderHandlerAnnotationImpl implements OrderHandlerAnnotation {
private String source;
private String payMethod;
public OrderHandlerAnnotationImpl(String source, String payMethod) {
this.source = source;
this.payMethod = payMethod;
}
@Override
public String source() {
return source;
}
@Override
public String payMethod() {
return payMethod;
}
@Override
public Class<? extends Annotation> annotationType() {
return OrderHandlerAnnotation.class;
}
@Override
public int hashCode() {
int hashCode = 0;
hashCode += (127 * "source".hashCode()) ^ source.hashCode();
hashCode += (127 * "payMethod".hashCode()) ^ payMethod.hashCode();
return hashCode;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof OrderHandlerAnnotation)) {
return false;
}
OrderHandlerAnnotation other = (OrderHandlerAnnotation) obj;
return source.equals(other.source()) && payMethod.equals(other.payMethod());
}
}
3.定义一个OrderHandlerAnnotation注解,来表示某个类是用来处理何种来源的订单。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface OrderHandlerAnnotation {
String source();
String payMethod();
}
4.接下来就是实现pc端和移动端订单处理各自的handler,并加上我们所定义的OrderHandlerAnnotation注解。
@OrderHandlerAnnotation(source = "pc",payMethod = "aliPay")
public class PcAliPayOrderHandler implements OrderHandler {
@Override
public void handle(OmsOrder order) {
System.out.println("处理PC端支付宝支付订单");
}
}
@OrderHandlerAnnotation(source = "pc",payMethod = "wxPay")
public class PcWxPayOrderHandler implements OrderHandler {
@Override
public void handle(OmsOrder order) {
System.out.println("处理PC端微信支付订单");
}
}
@OrderHandlerAnnotation(source = "mobile",payMethod = "aliPay")
public class MobileAliPayOrderHandler implements OrderHandler {
@Override
public void handle(OmsOrder order) {
System.out.println("处理移动端支付宝支付订单");
}
}
@OrderHandlerAnnotation(source = "mobile",payMethod = "wxPay")
public class MobileWxPayOrderHandler implements OrderHandler {
@Override
public void handle(OmsOrder order) {
System.out.println("处理移动端微信支付订单");
}
}
5.以上准备就绪后,就是向spring容器中注入各种订单处理的handler,并在OrderService.orderService方法中,通过策略(订单来源)去决定选择哪一个OrderHandler去处理订单。我们可以这样做:
@Service
public class OmsOrderServiceImpl extends ServiceImpl<OmsOrderMapper, OmsOrder> implements OmsOrderService {
private Map<OrderHandlerAnnotation, OrderHandler> orderHandleMap;
@Autowired
public void setOrderHandleMap(List<OrderHandler> orderHandlers) {
// 注入各种类型的订单处理类
orderHandleMap = orderHandlers.stream().collect(
Collectors.toMap(orderHandler -> AnnotationUtils.findAnnotation(
orderHandler.getClass(), OrderHandlerAnnotation.class),v -> v, (v1, v2) -> v1));
}
@Override
public void orderhandle(OmsOrder order) {
// ...一些前置处理
// 通过订单来源确定对应的handler
OrderHandlerAnnotation orderHandlerAnnotation = new OrderHandlerAnnotationImpl(order.getSource(), order.getPayMethod());
OrderHandler orderHandler = orderHandleMap.get(orderHandlerAnnotation);
orderHandler.handle(order);
// ...一些后置处理
}
}