前言 思路與模擬業務
源碼地址 https://gitee.com/houzheng1216/springboot
整體思路就是通過注解在策略類上指定約定好的type,項目啟動之后將所有有注解的type獲取到,根據type存儲,然后在業務中根據type獲取對應的策略即可
模擬訂單業務,根據訂單的type,需要不同的處理邏輯,比如,免費訂單,半價訂單等,下面是項目結構:

一 策略接口和實現
/** * 處理訂單策略 */ public interface OrderStrategy { void handleOrder(Order order); }
@Component @HandlerOrderType(Order.FREE) //使用注解標明策略類型 public class FreeOrderStrategy implements OrderStrategy { @Override public void handleOrder(Order order) { System.out.println("----處理免費訂單----"); } }
@Component @HandlerOrderType(Order.HALF) public class HalfOrderStrategy implements OrderStrategy { @Override public void handleOrder(Order order) { System.out.println("----處理半價訂單----"); } }
@Component @HandlerOrderType(Order.DISCOUT) public class DiscoutOrderStrategy implements OrderStrategy { @Override public void handleOrder(Order order) { System.out.println("----處理打折訂單----"); } }
二 自定義策略注解
@Target(ElementType.TYPE) //作用在類上 @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited //子類可以繼承此注解 public @interface HandlerOrderType { /** * 策略類型 * @return */ int value(); }
此處只能用基本類型或者String,約定的類型放在Order實體類里
三 業務實體
public class Order { public static final int FREE=1; //免費訂單 public static final int HALF=2; //半價訂單 public static final int DISCOUT=3; //打折訂單 private String name; private Double price; private Integer type;//訂單類型 public static Order build(){ return new Order(); }
四 核心功能實現
主要就是這一塊實現策略邏輯
/** * 根據訂單類型返回對應的處理策略 */ @Component public class HandlerOrderContext { @Autowired private ApplicationContext applicationContext; //存放所有策略類Bean的map public static Map<Integer, Class<OrderStrategy>> orderStrategyBeanMap= new HashMap<>(); public OrderStrategy getOrderStrategy(Integer type){ Class<OrderStrategy> strategyClass = orderStrategyBeanMap.get(type); if(strategyClass==null) throw new IllegalArgumentException("沒有對應的訂單類型"); //從容器中獲取對應的策略Bean return applicationContext.getBean(strategyClass); } }
/** * 策略核心功能,獲取所有策略注解的類型 * 並將對應的class初始化到HandlerOrderContext中 */ @Component public class HandlerOrderProcessor implements ApplicationContextAware { /** * 獲取所有的策略Beanclass 加入HandlerOrderContext屬性中 * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { //獲取所有策略注解的Bean Map<String, Object> orderStrategyMap = applicationContext.getBeansWithAnnotation(HandlerOrderType.class); orderStrategyMap.forEach((k,v)->{ Class<OrderStrategy> orderStrategyClass = (Class<OrderStrategy>) v.getClass(); int type = orderStrategyClass.getAnnotation(HandlerOrderType.class).value(); //將class加入map中,type作為key HandlerOrderContext.orderStrategyBeanMap.put(type,orderStrategyClass); }); } }
五 業務service使用
@Component public class OrderServiceImpl implements OrderService { @Autowired HandlerOrderContext handlerOrderContext; @Override public void handleOrder(Order order) { //使用策略處理訂單 OrderStrategy orderStrategy = handlerOrderContext.getOrderStrategy(order.getType()); orderStrategy.handleOrder(order); } }
很簡單,業務代碼以后基本不用再修改,不管添加多少策略或者需求變更多少次
六 controller測試
@RestController @RequestMapping("/order") public class OrderController { @Autowired OrderService orderService; @GetMapping("/handler/{type}") public void handleOrder(@PathVariable Integer type){ Order order = Order.build() .add("name", "微信訂單") .add("price", 99.9) .add("type", type); orderService.handleOrder(order); } }
使用鏈式風格構造對象
測試:

再添加策略添加實現類,啟用注解即可!
省去了工廠模式,直接用注解實現,避免修改工廠類,
這里貼一個我們之前項目的工廠類實現:

如果再添加策略還是會有輕微的改動!
