アドバンスドポイントのIf else:Springでの責任チェーンの使用


アドバンスドポイントのIf else:Springでの責任チェーンの使用
  • シーン説明
  • バックグラウンド
  • 難点
  • コード説明
  • 要点
  • キーコード
  • インタフェース&抽象クラス
  • 具体的な処理ノードは、例
  • である.
  • チェーン構成
  • 注入&
  • 使用
  • まとめ
  • シーンの説明
    背景
    本文の背景:微信公衆番号のバックグラウンドを開発し、ユーザーが入力したキーワードに対して相応の返事を行う必要がある.従来のIf elseを採用すると,多数の判断分岐と業務実装コードが同一クラスに混在しており,複数人が開発する際にコード競合が発生しやすく,切コードが読みにくく,分岐調整ニーズが発生した場合にも勝手に調整することが困難であることが分かった.したがって,各条件分岐における処理ロジックを分離し,随時構成調整が可能なモードが必要である.
    難点
    上記のシーンの説明から、責任チェーン設計モデルを考えるのは難しくありませんが、特別な点は、私たちのビジネス処理部分がいくつかのクエリー操作を行う必要があるときにSpring管理のいくつかのサービスクラスを使用し、責任チェーン処理ノードに注入する必要があることです.一般的なネットワーク上で見つかったチュートリアルはすべて手動宣言クラスであり、初期化されている場合、Springの特性に結合できません.Spring環境で責任チェーン設計モデルをどのように使用するかを説明する記事が見つかりました.リンク
    コードの説明
    要点
  • ゲートウェイzulのfilter構成スタイルを参照すると、doParse,order,parserTypeの3つの重要なパラメータが含まれ、複数のビジネスブランチに対して複数の責任チェーン
  • を構成することができます.
  • Springは、1つのインタフェースのすべてのインプリメンテーションクラスを一度に
  • にロードすることをサポートします.
  • Orderedインタフェースを借りて責任チェーンの前後順位
  • を実現する
    キーコード
    インタフェース&抽象クラス
    まずParserの基礎が必要で、一つのことをします.
    /*
     *       
     */
    public interface ISupport {
      void doParse(ChainRequestWrapper wrapper) throws Exception;
    }
    
    /*
     *       
     */
    public abstract AbsSupport implements ISupport, Ordered {
      protected AbsSupport support;
      protected boolean shouldParse = false;//        
      protected String parserType;
      protected int order = Ordered.LOWEST_PRECEDENCE;//     
      // ...     getter setter
    }
    
    /*
     *       
     */
    public class ChainRequestWrapper {
       WxMsgDTO dto;
       boolean shouldParse = true;//          
       // ... getter setter
    }
    

    以上、WxMsgDTOの具体的な内容は、微信開発ドキュメント、XMLで記述された構造を参照している.一般的には、doParsefromUserNametoUserNameなどのフィールドが使用されます.ここでのshouldParseは,各Supportノードの処理過程において,1つの処理が完了し,これ以上転送しない場合はfalseに設定すればよい.
    具体的な処理ノードの例
    このノードはAbsSupportダミークラスを継承すればよい
    /*
    *        
    */
    public class DefaultUnparseableSupport extends AbsSupport {
      //               
      public DefaultUnparseableSupport( 
        @Value("${parser.defaultUnparseableSupport.shouldParse"}) boolean shouldParse,
        @Value("${parser.defaultUnparseableSupport.order"}) int order,
        @Value("${parser.defaultUnparseableSupport.parserType"}) String parserType,
      ) {
      //          
      this.shouldParse = shouldParse;
      this.order = order;
      this.parserType = parserType;
      }
    
     @Override
     public getOrder() {
       return this.order;
     }
     @Override
     public boolean shouldParse(ChainRequestWrapper wrapper) {
       //                
       return wrapper.isShouldParse() && this.shouldParse;
     }
     @Override
     public String getParserType() {
       return this.parserType;
     }
     @Override
     public void doParse(ChainRequestWrapper wrapper) throws Exception {
       if(shouldParse(wrapper)) {
         WxMsgDTOUtil.swapUserAndSetText(wrapper.getDto(), "      ");
         wrapper.setShouldParse(false); //     false               
       }
     }
    }
    

    チェーン構成
    上記のコードに従ってプロファイルにshouldParse,order,parserTypeなどの重要な構成を配置すればよい
    parser.defaultUnparseableSupport.shouldParse=true
    parser.defaultUnparseableSupport.order=9999 #       
    parser.defaultUnparseableSupport.parserType=test
    # .....
    

    注入&使用
    プログラム起動時にチェーンを注入し、必要な場所で使用すればよい
    //   
    @Component
    public class SomeParserManager {
    
      List<AbsSupport> supportList;
      public SomeParserManager(@Autowired List<AbsSupport> supportList) {
        //              ,    test     
        this.supportList = supportList.stream().filter(item -> item.getParserType().equals("test")).collect(Collectors.toList());
        Collections.sort(this.supportList,AnnotationAwareOrderCompareator.INSTANCE);
      }
    
      public void doParse(WxMsgDTO dto) {
        //           wrapper        
        ChainRequestWrapper wrapper = new ChainRequestWrapper();
        wrapper.setDto(dto);
        wrapper.setShouldParse(true);
        for(AbsSupport support: supportList) {
          support.doParse(wrapper);
        }
        //          wrapper                 ,      wrapper  
        // toTextXmlString                   ,          。
        return wrapper.getDto().toTextXmlString();
      }
    }
    

    まとめ
    従来のif elseブランチから責任チェーンに変更する利点は、複数人が協力して開発している間、一人一人が責任を負うブランチを独立して作成することができ、相互に織りなすことなく、配置に応じてブランチの流れと前後順序を柔軟に変更することができることです.