본문 바로가기

JAVA/디자인 패턴

[Design Pattern] Chain of Responsibility(책임 연쇄) 패턴이란?

반응형
행위 패턴(Behavioral Pattern)


책임 연쇄 패턴(Chain of Responsibility)은 객체들이 연결된 체인 형태로 존재하며, 각 객체가 요청을 처리하지 못할 경우 다음 객체에게 책임을 전달하고, 다음 객체 또한 처리하지 못하면 다시 다음 객체로 전달하는 패턴입니다.

이 패턴은 객체 간의 결합도를 낮추고, 요청을 처리할 객체를 동적으로 결정하는 데 유용합니다. 요청 처리 과정에서 요청을 처리할 객체를 직접 지정하지 않아도 되므로, 클라이언트 코드와 서버 코드 간의 결합도가 낮아집니다.

이 패턴의 구성요소로는 요청(Request) 객체, 처리자(Handler) 인터페이스, 처리자 구현체, 그리고 체인 연결 방법이 있습니다. 요청 객체는 처리를 요청하는 객체를 나타내며, 처리자 인터페이스는 요청 처리 메서드를 정의합니다. 처리자 구현체는 실제 요청 처리를 담당합니다. 마지막으로, 체인 연결 방법은 각 처리자가 다음 처리자를 참조할 수 있도록 체인 형태로 객체를 연결하는 방법을 말합니다.

책임 연쇄 패턴은 예를 들어 로그인 처리나 예외 처리와 같은 경우에 유용하게 사용될 수 있습니다. 이를 통해 요청 처리 과정에서 각 객체가 책임을 나누어 처리할 수 있으므로, 코드 유지 보수성과 확장성을 높일 수 있습니다.

 

 

책임 연쇄 패턴(Chain of Responsibility)의 장단점

장점

  1. 유연성: 요청 처리 과정에서 처리를 담당할 객체를 동적으로 변경할 수 있습니다.
  2. 확장성: 새로운 객체를 체인에 추가하여 요청 처리를 확장할 수 있습니다.
  3. 간결성: 클라이언트 코드에서 처리할 객체를 직접 선택할 필요가 없으므로 코드가 간결해집니다.
  4. 유지보수성: 요청 처리 과정에서 변경이 필요한 부분을 처리할 객체만 수정하면 되므로 유지보수성이 향상됩니다.

단점

  1. 성능 문제: 체인에 많은 객체가 연결되어 있을 경우, 요청 처리 과정이 느려질 수 있습니다.
  2. 처리 보장 문제: 처리를 담당하는 객체가 체인에서 발견되지 않을 경우, 요청 처리가 보장되지 않을 수 있습니다.
  3. 디버깅 문제: 어떤 객체가 요청 처리를 담당하고 있는지 추적하기 어렵기 때문에 디버깅이 어려울 수 있습니다.

책임 연쇄 패턴(Chain of Responsibility) 예제

Java에서 "Chain of Responsibility" 패턴을 구현하는 가장 간단한 방법은 인터페이스를 정의하고 이를 구현하는 여러 클래스를 만드는 것입니다. 다음은 이에 대한 예제입니다.

Diagrams


먼저, 요청(Request)을 나타내는 클래스를 작성합니다.

public class Request {
    private String type;
    private String message;

    public Request(String type, String message) {
        this.type = type;
        this.message = message;
    }

    public String getType() {
        return type;
    }

    public String getMessage() {
        return message;
    }
}



다음으로, 요청을 처리하는 핸들러(Handler) 인터페이스를 정의합니다.

public interface Handler {
    void setNext(Handler handler);
    void handleRequest(Request request);
}



그리고 이 인터페이스를 구현하는 여러 핸들러 클래스를 만듭니다.

public class FirstHandler implements Handler {
    private Handler nextHandler;

    @Override
    public void setNext(Handler handler) {
        nextHandler = handler;
    }

    @Override
    public void handleRequest(Request request) {
        if (request.getType().equals("type1")) {
            System.out.println("Type 1 request handled by FirstHandler: " + request.getMessage());
        } else if (nextHandler != null) {
            // 다음 handler에 처리를 전가
            nextHandler.handleRequest(request);
        }
    }
}

public class SecondHandler implements Handler {
    private Handler nextHandler;

    @Override
    public void setNext(Handler handler) {
        nextHandler = handler;
    }

    @Override
    public void handleRequest(Request request) {
        if (request.getType().equals("type2")) {
            System.out.println("Type 2 request handled by SecondHandler: " + request.getMessage());
        } else if (nextHandler != null) {
            // 다음 handler에 처리를 전가
            nextHandler.handleRequest(request);
        }
    }
}

public class ThirdHandler implements Handler {
    private Handler nextHandler;

    @Override
    public void setNext(Handler handler) {
        nextHandler = handler;
    }

    @Override
    public void handleRequest(Request request) {
    	if (request.getType().equals("type3")) {
            System.out.println("Type 3 request handled by ThirdHandler: " + request.getMessage());
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            // 다음 handler가 없기때문에 처리를 전가하지않음
            System.out.println("Request not handled.");
        }
    }
}



마지막으로, 핸들러 객체를 연결하여 체인을 형성하는 클래스를 작성합니다.

public class Main {
    public static void main(String[] args) {
        Handler firstHandler = new FirstHandler();
        Handler secondHandler = new SecondHandler();
        Handler thirdHandler = new ThirdHandler();

        firstHandler.setNext(secondHandler);
        secondHandler.setNext(thirdHandler);

        Request request1 = new Request("type1", "Request 1");
        Request request2 = new Request("type2", "Request 2");
        Request request3 = new Request("type3", "Request 3");
        Request request4 = new Request("type4", "Request 4");

        firstHandler.handleRequest(request1);
        firstHandler.handleRequest(request2);
        firstHandler.handleRequest(request3);
        firstHandler.handleRequest(request4);
    }
}


위 예제에서는 FirstHandler, SecondHandler, ThirdHandler 세 개의 핸들러 클래스를 만들었고, 체인을 형성하기 위해 setNext() 메서드를 사용하여 핸들러 객체를 연결했습니다. 마지막으로, handleRequest() 메서드를 호출하여 요청 객체를 체인에 전달하고, 적절한 핸들러에서 요청을 처리하도록 했습니다.

이 예제를 실행하면 다음과 같은 결과가 출력됩니다.

Type 1 request handled by FirstHandler: Request 1
Type 2 request handled by SecondHandler: Request 2
Type 3 request handled by ThirdHandler: Request 3
Request not handled.


첫 번째 요청은 FirstHandler에서 처리되고, 두 번째 요청은 SecondHandler에서 처리됩니다. 세 번째 요청은 ThirdHandler에서 처리되고, 네 번째 요청은 어떤 핸들러에서도 처리되지 않습니다. 이는 ThirdHandler에서 요청을 처리할 수 없는 타입의 요청이기 때문입니다.

 

 

반응형