PSD( Private-Self-Development )

책임 연쇄 패턴( 체인 패턴 ) 본문

Backend/디자인패턴

책임 연쇄 패턴( 체인 패턴 )

chjysm 2023. 8. 9. 13:20

책임 연쇄 패턴?

요청을 핸들러들의 체인에 따라 전달하고 처리하는 행동 디자인 패턴이다.

ex ) 로그인 요청이 들어왔을 때, 순차적인 A 검증, B 검증, C 검증 중  B 검증에 실패한 경우 C 검증은 진행하지 않아야 한다.

이때, 책임 연쇄 패턴을 적용하여 같은 Interface 를 구현한 각각의 핸들러들의 체인으로 구성하면 유지보수성이 향상된다.

 

책임 연쇄 패턴의 구성 요소

  • Handler
    • 모든 ConcreteHanlers 에 적용되는 공통 인터페이스 
    • 보통은 요청 처리용 단일 메서드만 포함되지만 
      때로는 체인의 다음 핸들러를 세팅하기 위한 메서드를 구현하는 경우도 있다.
  • BaseHandler
    • 선택적 클래스 
    • ConcreteHanlers 에 공통적으로 적용되는 코드를 구현한다.
    • 다음 핸들러에 대한 참조를 저장하기 위한 필드를 정의한다.
  • ConcreteHandlers
    • 요청을 처리하기 위한 실 코드 작성
    • 요청을 받으면 요청을 처리할지 체인을 따라 전달할지 결정 
  • Client
    • 체인들을 동적 으로 구성할 수 있다.
    • 체인의 모든 핸들러에 요청 가능 꼭 첫 번째 핸들러일 필요는 없다.
    • 파사드 패턴을 적용하여 각 조건 별로 체인을 구성하면 좋을 듯 하다.

 

책염 연쇄 패턴의 장점

  • 요청의 처리 순서를 제어 할 수 있다.
  • 단일 책임 원칙
  • 개방/폐쇄 원칙
  • 유지보수성 향상

책임 연쇄 패턴의 단점

  • 체인 구성에 따라
    특정 처리를 위해, 모든 체인을 거쳐 진행될 수 있다. (처리 지연)

 

책임 연쇄 패턴의 구현

public abstract class AuthHandler {
    protected AuthHandler next;

    public AuthHandler setNext(AuthHandler authHandler) {
        this.next = authHandler;
        return this;
    }

    public abstract void execute( String eventName );
}

public class AuthA extends AuthHandler{
    @Override
    public void execute(String eventName) {
        System.out.println("A");

        this.next.execute(eventName);
    }
}

public class AuthB extends AuthHandler{
    @Override
    public void execute(String eventName) {
        if( "B".equals( eventName ) ){
            System.out.println("B");
        }

        this.next.execute(eventName);
    }
}

public class AuthC extends AuthHandler{
    @Override
    public void execute(String eventName) {
        System.out.println("C");

        this.next.execute(eventName);
    }
}

public class Facade {
    public static AuthHandler makeChainA(){
        AuthHandler first = new AuthA();
        AuthHandler second = new AuthB();
        AuthHandler third = new AuthC();

        return first.setNext(second.setNext(third));
    }
    public static AuthHandler makeChainB(){
        AuthHandler second = new AuthB();
        AuthHandler third = new AuthC();

        return second.setNext(third);
    }
}

public class Client {
	public static void main(String[] args) {
        AuthHandler authHandler = Facade.makeChainA();
        authHandler.execute("B");
    }
}

 

언제 사용해야 할까?

  • 다양한 방식으로 다양한 종류의 요청들을 처리할 것으로 예상되지만 유형 및 순서를 미리 알 수 없는 경우
  • 특정 순서로 여러 핸들러를 실행해야 하는 경우
  • 핸들러들의 순서가 런타임에 변경되어야 하는 경우

 

 


참조

https://refactoring.guru/ko/design-patterns/chain-of-responsibility

'Backend > 디자인패턴' 카테고리의 다른 글

방문자 패턴  (0) 2023.05.31
명령 패턴  (0) 2023.05.30
플라이웨이트 패턴  (0) 2023.05.23
파사드 패턴  (0) 2023.05.23
장식자 패턴  (0) 2023.05.22