<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      前言:

      之前寫過一個工作中常見升級模式-策略模式?的文章,里面講了具體是怎樣使用策略模式去抽象現(xiàn)實中的業(yè)務代碼,今天來拿出實際代碼來寫個demo,這里做個整理來加深自己對策略模式的理解。
      ?
      一、業(yè)務流程
      取消訂單會有多種情況,比如:取消即時訂單、取消預約訂單、取消拼車訂單 ?
      一般業(yè)務代碼中我們會根據(jù)取消類型來進行不同的邏輯處理,代碼中無外乎多了很多if?else的業(yè)務邏輯,且代碼耦合度很高。 ?
      那么有沒有一種優(yōu)雅的處理方式呢??當然有了,現(xiàn)在就來說下我們系統(tǒng)中是如何處理這種問題的(?具體業(yè)務需求可以參考我上一篇文章:
      https://www.cnblogs.com/wang-meng/p/11457544.html
      <https://www.cnblogs.com/wang-meng/p/11457544.html>) ?
      二、流程圖
      上面已經說了業(yè)務流程,當然有流程圖才是最直觀的,這里我們可以直接參見下圖: ? ?
      這里我們可以使用Spring?獲取到所有?AbstractOrderStrategy?實現(xiàn)類中@OrderTypeAnnotation注解的類,然后比較orderType即可。下面就看具體代碼吧;
      ?
      三、代碼實現(xiàn)及解析
      1、自定義訂單類型枚舉:OrderTypeAnnotation ? 1 @Target({ElementType.TYPE}) 2
      @Retention(RetentionPolicy.RUNTIME)3 public @interface OrderTypeAnnotation { 4
      OrderTypeEnum orderType();5 } 這里
      ElementType.TYPE表示用于類上,RetentionPolicy.RUNTIME?表示運行時解析的。更多的含義大家可以看注解的相關知識。 ?
      2、構建OrderType枚舉:OrderTypeEnum 1 public enum OrderTypeEnum { 2 INSTANT(1,
      "即時訂單"), 3 BOOKING(2, "預約訂單"), 4 CARPOOL(3, "拼車訂單"); 5 6 7 private int
      code; 8 private String desc; 9 10 11 OrderTypeEnum(int code, String desc) { 12
      this.code = code; 13 this.desc = desc; 14 } 15 16 17 public int getCode() { 18
      return code; 19 } 20 21 22 public String getDesc() { 23 return desc; 24 } 25
      26 27 public static OrderTypeEnum getByCode(int code) { 28 for (OrderTypeEnum
      orderTypeEnum : values()) {29 if (orderTypeEnum.getCode() == code) { 30 return
      orderTypeEnum;31 } 32 } 33 return null; 34 } 35 }
      ?
      ? 這里會顯示該取消訂單的類型,如過往代碼中所有if?中的條件判斷,這里用枚舉進行歸納。 ? 3、構建抽象策略及策略實現(xiàn)類 ?
      策略抽象類:AbstractOrderStrategy ? 1 public abstract class AbstractOrderStrategy { 2
      3 /** 4 * 策略抽象方法 5 * @param orderDTO 6 */ 7 abstract public void
      process(OrderDTO orderDTO);8 } ? 為了容易理解,這里只有一個業(yè)務實現(xiàn)類,繼承該抽象類的策略類都會實現(xiàn)具體的業(yè)務。 ?
      預約單處理策略類:BookingOrderStrategy 1 @Service 2 @OrderTypeAnnotation(orderType =
      OrderTypeEnum.BOOKING)3 public class BookingOrderStrategy extends
      AbstractOrderStrategy {4 5 @Override 6 public void process(OrderDTO orderDTO) {
      7 System.out.println("取消預約訂單"); 8 } 9 } ?
      這里重點關注orderType,代碼區(qū)分具體的執(zhí)行策略?都是通過這個type去進行處理的。 ? 即時單處理策略類:InstantOrderStrategy ?
      1 @Service 2 @OrderTypeAnnotation(orderType = OrderTypeEnum.INSTANT) 3 public
      class InstantOrderStrategy extends AbstractOrderStrategy { 4 5 @Override 6
      public void process(OrderDTO orderDTO) { 7 System.out.println("取消即時訂單"); 8 } 9
      } ? 4、策略分發(fā)處理類 ?
      這個類主要是接收業(yè)務請求,然后轉發(fā)到具體的策略類進行處理,這里使用到了spring?獲取具體的類,然后通過類上面的注解信息進行轉發(fā)。 1 @Service
      2 @Slf4j 3 public class CancelOrderStrategyService { 4 /** 5 * 處理取消邏輯 6 */
      7 public void process(OrderDTO orderDTO) { 8 Map<String,
      AbstractOrderStrategy> beanMap =
      SpringBeanUtils.getBeanMap(AbstractOrderStrategy.class); 9 try { 10 for
      (Map.Entry<String, AbstractOrderStrategy> entry : beanMap.entrySet()) { 11
      Object real = SpringBeanUtils.getTarget(entry.getValue()); 12
      OrderTypeAnnotation annotation =
      real.getClass().getAnnotation(OrderTypeAnnotation.class); 13 if
      (orderDTO.getServiceType() == annotation.orderType().getCode()) { 14
      entry.getValue().process(orderDTO);15 break; 16 } 17 } 18 } catch (Exception
      e) {19 log.error("獲取目標代理對象失敗:{}", e); 20 } 21 } 22 }
      ?
      其中: Map<String, AbstractOrderStrategy> beanMap =
      SpringBeanUtils.getBeanMap(AbstractOrderStrategy.class);
      代表獲取AbstractOrderStrategy 下全部子類或接口。 ? Object real =
      SpringBeanUtils.getTarget(entry.getValue()); 代表獲取具體的代理類 ? OrderTypeAnnotation
      annotation = real.getClass().getAnnotation(OrderTypeAnnotation.class);
      代表取類上有OrderTypeAnnotation 的注解信息。 ? CancelOrderStrategyService.process()
      ?這個方法是可以擴展的,通過外部傳入的class信息來獲取具體的代理類。 ? ? 5、Spring獲取bean工具類 1 @Component 2
      public class SpringBeanUtils implements ApplicationContextAware { 3 private
      static ApplicationContext applicationContext; 4 5 @Override 6 public void
      setApplicationContext(ApplicationContext context)throws BeansException { 7 if
      (applicationContext ==null) { 8 applicationContext = context; 9 } 10 } 11 12
      public static Object getBean(String name) { 13 return
      applicationContext.getBean(name);14 } 15 16 public static <T> T
      getBean(Class<T> clazz) { 17 return applicationContext.getBean(clazz); 18 } 19
      20 /** 21 * 獲取類型為requiredType的Map 22 * 23 * @param clazz 24 * @return 25 */
      26 public static <T> Map<String, T> getBeanMap(Class<T> clazz) { 27 return
      applicationContext.getBeansOfType(clazz);28 } 29 30 /** 31 * 獲取 目標對象 32 * 33
      *@param proxy 代理對象 34 * @return 目標對象 35 * @throws Exception 36 */ 37 public
      static Object getTarget(Object proxy) throws Exception { 38 if (!
      AopUtils.isAopProxy(proxy)) {39 // 不是代理對象,直接返回 40 return proxy; 41 } 42 43 if
      (AopUtils.isJdkDynamicProxy(proxy)) {44 return
      getJdkDynamicProxyTargetObject(proxy);45 } else { 46 // cglib 47 return
      getCglibProxyTargetObject(proxy);48 } 49 } 50 51 private static Object
      getJdkDynamicProxyTargetObject(Object proxy)throws Exception { 52 Field field =
      proxy.getClass().getSuperclass().getDeclaredField("h"); 53 field.setAccessible(
      true); 54 AopProxy aopProxy = (AopProxy) field.get(proxy); 55 Field advised =
      aopProxy.getClass().getDeclaredField("advised"); 56 advised.setAccessible(true);
      57 58 Object target = ((AdvisedSupport)
      advised.get(aopProxy)).getTargetSource().getTarget();59 return target; 60 } 61
      62 private static Object getCglibProxyTargetObject(Object proxy) throws
      Exception {63 Field field = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0"
      );64 field.setAccessible(true); 65 Object dynamicAdvisedInterceptor =
      field.get(proxy);66 67 Field advised =
      dynamicAdvisedInterceptor.getClass().getDeclaredField("advised"); 68
      advised.setAccessible(true); 69 70 Object target = ((AdvisedSupport)
      advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();71 return
      target;72 } 73 }
      ?
      ? 6、添加單元測試 public class CancelAbstractOrderStrategyTest extends BaseTest {
      @Autowiredprivate CancelOrderStrategyService cancelOrderStrategyService; @Test
      public void process() { OrderDTO orderDTO = new OrderDTO();
      orderDTO.setServiceType(OrderTypeEnum.INSTANT.getCode());
      cancelOrderStrategyService.process(orderDTO); } } ? 7、打印結果: 1 取消即時訂單 ?
      到了這里代碼就已經寫完了,如果仔細看的話?應該會明白這里的設計思路,通過策略模式+注解?可以大大的降低業(yè)務的耦合度,而且也極大的方便了后期維護的工作量。 ?
      部分代碼參考:https://www.cnblogs.com/HelloDeveloper/p/11390512.html
      <https://www.cnblogs.com/HelloDeveloper/p/11390512.html>, 這里對核心類做了修改和精簡。

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          小早川怜子东京热无码 | av看片app下载 | 国产免费操 | 啊轻点灬又粗又长第一次 | 久热草视频| 免费看一级黄色片 | 爱爱综合在线 | 日韩一区在线电影 | 天天摸天天| 卡戴珊裸乳无打码 |