一般的な設計パターンの責任連鎖モデル

概念

責任の連鎖パターン(責任の連鎖パターン)は、チェーン内の各ノードをオブジェクトとして扱い、各ノードは異なる要求を処理し、次のノードオブジェクトを内部的に維持します。チェーンの最初のセグメントからリクエストが送信されると、オブジェクトがリクエストを処理するまで、チェーンのパスに沿って各ノードオブジェクトに順番に渡されます。このタイプの設計パターンは行動パターンです。
責任の連鎖モデルには、主に2つの役割が含まれます。

  • 抽象ハンドラー(ハンドル):処理メソッドを定義し、次の処理ノードのハンドルオブジェクトへの参照を維持します。
  • コンクリートハンドル(ConcreteHandle):リクエストを処理し、関心がない場合は転送します。

成し遂げる

次に、例としてログイン検証を取り上げます

1.抽象ハンドラーを作成します

public abstract class Handle {
    
    
    protected Handle chain;

    public void next(Handle handle){
    
    
        this.chain=handle;
    }

    public abstract void doHandle(Member member);
}

2.特定のプロセッサ

public class ValidateHadle extends Handle {
    
    
    @Override
    public void doHandle(Member member) {
    
    
        if("".equals(member.getName())||"".equals(member.getPwd())){
    
    
            System.out.println("用户名或密码为空");
            return;
        }
        System.out.println("用户名密码格式校验完毕");
        chain.doHandle(member);
    }
}
public class LoginHandle extends Handle {
    
    
    @Override
    public void doHandle(Member member) {
    
    
        System.out.println("登陆成功");
        chain.doHandle(member);
    }
}
public class AuthHandle extends Handle {
    
    
    @Override
    public void doHandle(Member member) {
    
    
        System.out.println("欢迎管理员!");
    }
}

3.テスト

public class ChainTest {
    
    
    public static void main(String[] args) {
    
    
        Handle validateHandle=new ValidateHadle();
        Handle loginHandle=new LoginHandle();
        Handle authHandle=new AuthHandle();
        validateHandle.next(loginHandle);
        loginHandle.next(authHandle);
        validateHandle.doHandle(new Member("tom","123"));
    }
}

動作結果:
ここに写真の説明を挿入

使用するシーン

  • オブジェクトごとに同じリクエストが処理されますが、特定のオブジェクト処理は実行時に動的に決定されます
  • 受信者を明確に指定せずに、複数のオブジェクトの1つにリクエストを送信します
  • リクエストを処理するオブジェクトのグループを動的に指定できます

SpringFrameworkでのアプリケーション

JDKには、非常に一般的なクラスFilterがあります

public interface Filter {
    
    
    public void init(FilterConfig filterConfig) throws ServletException;
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;
    public void destroy();

}

このフィルターインターフェイスは非常にシンプルで、責任の連鎖におけるハンドル抽象ロールと同等です。もう一度見てくださいdoFilterFilterChainクラスメソッドの最後のパラメーター

public interface FilterChain {
    
    
    public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException;

}

1つだけが定義されていますdoFilter方法、それらはどのように接続してチェーンを形成しますか?SpringのMockFilterChainクラスの実装を見てみましょう

public class MockFilterChain implements FilterChain {
    
    

	private ServletRequest request;

	private ServletResponse response;

	private final List<Filter> filters;

	private Iterator<Filter> iterator;
	public MockFilterChain() {
    
    
		this.filters = Collections.emptyList();
	}
	public MockFilterChain(Servlet servlet) {
    
    
		this.filters = initFilterList(servlet);
	}
	public MockFilterChain(Servlet servlet, Filter... filters) {
    
    
		Assert.notNull(filters, "filters cannot be null");
		Assert.noNullElements(filters, "filters cannot contain null values");
		this.filters = initFilterList(servlet, filters);
	}

	private static List<Filter> initFilterList(Servlet servlet, Filter... filters) {
    
    
		Filter[] allFilters = ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet));
		return Arrays.asList(allFilters);
	}
	public ServletRequest getRequest() {
    
    
		return this.request;
	}
	public ServletResponse getResponse() {
    
    
		return this.response;
	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
    
    
		Assert.notNull(request, "Request must not be null");
		Assert.notNull(response, "Response must not be null");
		Assert.state(this.request == null, "This FilterChain has already been called!");

		if (this.iterator == null) {
    
    
			this.iterator = this.filters.iterator();
		}

		if (this.iterator.hasNext()) {
    
    
			Filter nextFilter = this.iterator.next();
			nextFilter.doFilter(request, response, this);
		}

		this.request = request;
		this.response = response;
	}
}

チェーンのすべてのフィルターをリストに入れてから、doFilterこの方法は、リストを反復することです。つまり、リスト内のフィルターは、
次のようにUMLクラス図を順番に実行します。
ここに写真の説明を挿入

総括する

利点

  1. 要求を処理から切り離します
  2. オブジェクトを簡略化しました。オブジェクトがチェーン構造を知る必要がないように
  3. リンク構造は柔軟であり、リンク構造の順序を変更することにより、責任を動的に追加または削除できます。
  4. 新しいリクエスト処理クラスを簡単に拡張できます

不利益

  1. 責任の連鎖が長すぎると、処理時間が長くなり、全体的なパフォーマンスに影響を及ぼします。
  2. ノードオブジェクトに循環参照がある場合、無限ループが発生し、システムがクラッシュします

おすすめ

転載: blog.csdn.net/xzw12138/article/details/106711267