Skip to main content

[Design Pattern] 행동 패턴 6. 책임 연쇄 (Chain of responsibility)




책임 연쇄 (Chain of responsibility) #

책임 연쇄

  • 주어진 요청을 처리하기 위해서 객체 사슬을 생성하고, 이 요청은 사슬을 따라 전달되면서 적절한 핸들러에 의해 처리되게 한다.



개념적인 예시 #

// 핸들러는 핸들러들의 체인을 만든다. 
// 요청을 처리할 동작도 정의되어 있다. 
public interface IHandler
{
    IHandler SetNext(IHandler handler);
    object Handle(object request);
}

abstract class AbstractHandler : IHandler
{
    private IHandler _nextHandler;

    // 기본 메서드를 베이스 클래스에서 구현할 수 있다. 
    public IHandler SetNext(IHandler handler)
    {
        this._nextHandler = handler;
        
        // 핸들러를 리턴한다. 
        // 이렇게 함으로써 아래 코드처럼 핸들러들을 연결시킬 수 있다. 
        // monkey.SetNext(squirrel).SetNext(dog);
        return handler;
    }
    
    public virtual object Handle(object request)
    {
        if (this._nextHandler != null)
        {
            return this._nextHandler.Handle(request);
        }
        else
        {
            return null;
        }
    }
}

class MonkeyHandler : AbstractHandler
{
    public override object Handle(object request)
    {
        if ((request as string) == "Banana")
        {
            return $"Monkey: I'll eat the {request.ToString()}.\n";
        }
        else
        {
            return base.Handle(request);
        }
    }
}

class SquirrelHandler : AbstractHandler
{
    public override object Handle(object request)
    {
        if (request.ToString() == "Nut")
        {
            return $"Squirrel: I'll eat the {request.ToString()}.\n";
        }
        else
        {
            return base.Handle(request);
        }
    }
}

class DogHandler : AbstractHandler
{
    public override object Handle(object request)
    {
        if (request.ToString() == "MeatBall")
        {
            return $"Dog: I'll eat the {request.ToString()}.\n";
        }
        else
        {
            return base.Handle(request);
        }
    }
}

class Client
{
    // 클라이언트는 한 개의 핸들러만 사용한다. 체인이 연결된지도 모른다. 
    public static void ClientCode(AbstractHandler handler)
    {
        var list = new List<string> { "Nut", "Banana", "Cup of coffee" };
        
        foreach (var food in list)
        {
            Console.WriteLine($"Client: Who wants a {food}?");

            var result = handler.Handle(food);

            if (result != null)
            {
                Console.Write($"   {result}");
            }
            else
            {
                Console.WriteLine($"   {food} was left untouched.");
            }
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var monkey = new MonkeyHandler();
        var squirrel = new SquirrelHandler();
        var dog = new DogHandler();

        // 체인 만들기 
        monkey.SetNext(squirrel).SetNext(dog);

        // Monkey -> Squirrel -> Dog
        Client.ClientCode(monkey);

        // Squirrel -> Dog
        Client.ClientCode(squirrel);
    }
}



References #