개인 공부/디자인패턴

디자인패턴 책임 연쇄 패턴 (Chain of Responsibility)

smallship 2024. 7. 16. 10:32

책임 연쇄 패턴은 요청을 처리할 수 있는 기회를 여러 객체에게 주며 요청을 보내는 객체와 그 요청을 처리할 수 있는 객체들 사이의 결합을 약화시키기 위해 사용된다.

 

 

  • Handler (처리자):
    • 요청을 처리할 인터페이스를 정의.
    • 체인 내에서 다음 처리자를 설정하거나, 자신이 마지막 처리자인지 여부를 판단하는 메서드를 포함할 수 있다.
  • ConcreteHandler (구체적인 처리자):
    • 실제로 요청을 처리하는 역할
    • 자신이 처리할 수 있는 요청의 종류를 판단하고 처리할 수 있다.
    • 요청을 처리할 수 없다면 다음 처리자로 요청을 전달할 수 있다.
  • Client (클라이언트):
    • 요청을 생성하고 체인의 첫 번째 처리자에게 전달한다.

 

책임 연쇄 패턴 구조

 

 


public interface IHandler
{
    void SetNext(IHandler handler);
    void HandleRequest(string request);
}

public abstract class Handler : IHandler
{
    protected IHandler nextHandler;
    
    public void SetNext(IHandler handler)
    {
        nextHandler = handler;
    }

    public abstract void HandleRequest(string request);
}

 

인터페이스와 추상 클래스 선언

 

  • IHandler 인터페이스: SetNext 메서드는 다음 처리자(Handler)를 설정하고, HandleRequest 메서드는 요청을 처리하는 방법을 정의한다.
  • Handler 추상 클래스: IHandler 인터페이스를 구현하며, nextHandler라는 다음 처리자를 가리키는 보호 필드를 포함한다. SetNext 메서드를 구현하여 다음 처리자를 설정하며, HandleRequest 메서드는 추상 메서드로 선언되어 구현은 서브클래스에게 위임한다.

 

 

public class Handler1 : Handler
{
    public override void HandleRequest(string request)
    {
        if (request == "Handler1")
        {
            // 구현부
            Debug.Log("Implement Handler1");
        }
        else if (nextHandler != null)
        {
            nextHandler.HandleRequest(request);
        }
    }
}

public class Handler2 : Handler
{
    public override void HandleRequest(string request)
    {
        if (request == "Handler2")
        {
            // 구현부
            Debug.Log("Implement Handler2");
        }
        else if (nextHandler != null)
        {
            nextHandler.HandleRequest(request);
        }
    }
}

 

구체적인 처리자 클래스 선언

 

  • Handler1 클래스: Handler 추상 클래스를 상속받아 HandleRequest 메서드를 구현한다. 만약 요청이 "Handler1"일 경우 처리하고, 그렇지 않으면 다음 처리자로 전달한다.
  • Handler2 클래스: 마찬가지로 Handler 추상 클래스를 상속받아 HandleRequest 메서드를 구현한다. 요청이 "Handler2"일 경우 처리하고, 그렇지 않으면 다음 처리자로 전달한다.

 

 

public class ChainOfResponsibility : MonoBehaviour
{
    void Start()
    {
        IHandler handler1 = new Handler1();
        IHandler handler2 = new Handler2();
        
        handler1.SetNext(handler2);
        
        handler1.HandleRequest("Handler1");
        handler1.HandleRequest("Handler2");
    }
}

 

체인 구성 및 실행

 

  • Start 메서드에서 Handler1과 Handler2를 생성하고, handler1에게 handler2를 다음 처리자로 설정한다.
  • handler1.HandleRequest("Handler1")은 "Handler1" 요청을 첫 번째 처리자에게 보내어 처리되는지 확인.
  • handler1.HandleRequest("Handler2")는 "Handler2" 요청을 첫 번째 처리자에게 보내어 처리되지 않고 두 번째 처리자로 전달되는지 확인.

책임 연쇄 패턴은 특히 요청을 처리하는 과정을 다양하게 설정하고 관리해야 하는 경우에 유용하며, 복잡한 처리 로직을 단순화하고 구조화하는 데 도움을 준다. 하지만 디버깅 및 유지보수에 어려움이 있고 충분한 디버깅을 거치지 않을 시 처리자들 간 무한루프가 발생할 수 있다. 이 패턴을 적용할 때에는 프로젝트의 요구사항과 환경을 잘 고려하여야 한다.