![[Design Pattern] 1](https://blog.kakaocdn.net/dn/d8ziN6/btr2tD2pS1k/lExJH63GYGFJZDQt7tgquk/img.png)
책임 사슬 패턴이란 무엇입니까?
책임 사슬 패턴은 객체의 처리를 순차적으로 연결된 핸들러 객체에 위임하고 이를 통해 요청을 처리하는 패턴입니다. 즉, 개체가 무언가를 처리해야 할 때 해당 프로세스를 담당하는 개체를 직접 호출하지 않고 요청을 받은 개체가 요청을 체인의 다음 개체로 전달합니다. 또한 핸들러 객체를 동적으로 추가하거나 삭제할 수 있으므로 핸들러 객체를 추가하거나 삭제하는 것만으로 프로그램 동작을 변경할 수 있습니다.
책임 사슬 패턴의 구성 요소
이 패턴은 일반적으로 다음 구성 요소로 구성됩니다.
- 처리기 인터페이스 또는 추상 클래스: 처리기 개체가 구현해야 하는 메서드를 정의합니다. 이 인터페이스 또는 추상 클래스에는 다음 핸들러 개체를 설정하기 위한 메서드와 요청을 처리하기 위한 메서드가 포함되어 있습니다.
- Class ConcreteHandler: 실제 처리를 담당하는 개체입니다. 이 클래스는 핸들러 인터페이스 또는 추상 클래스를 구현합니다.
- 클라이언트: 핸들러 개체를 연결하여 요청을 처리하는 개체입니다. 이 개체는 핸들러 개체 체인을 설정하고 요청을 보내는 일을 담당합니다.
클래스 다이어그램
다음 책임의 사슬 패턴의 클래스 다이어그램.
![[Design Pattern] 2](https://blog.kakaocdn.net/dn/KvPds/btr2xSLDFUC/olVvHqDPFvgABId1iZVfr0/img.png)
위의 다이어그램에서 Handler는 Handler 개체가 구현해야 하는 메서드를 정의하는 추상 클래스 또는 인터페이스입니다. 실제 처리를 담당하는 객체인 ConcreteHandler1, ConcreteHandler2, ConcreteHandler3 클래스는 Handler 클래스를 상속받아 handleRequest 메소드를 구현한다.
C++ 책임 사슬 패턴 예제
다음 책임의 사슬 패턴의 C++ 예제.
class Handler {
protected:
Handler* successor; // NEXT 처리기 객체
public:
virtual ~Handler() {}
void setSuccessor(Handler* next) { successor = next; }
virtual void handleRequest(int request) {
if (successor != nullptr) {
successor->handleRequest(request);
}
}
};
class ConcreteHandler1 : public Handler {
public:
void handleRequest(int request) override {
if (request >= 0 && request < 10) {
std::cout << "ConcreteHandler1 handles request " << request << std::endl;
}
else if (successor != nullptr) {
successor->handleRequest(request);
}
}
};
class ConcreteHandler2 : public Handler {
public:
void handleRequest(int request) override {
if (request >= 10 && request < 20) {
std::cout << "ConcreteHandler2 handles request " << request << std::endl;
}
else if (successor != nullptr) {
successor->handleRequest(request);
}
}
};
class ConcreteHandler3 : public Handler {
public:
void handleRequest(int request) override {
if (request >= 20 && request < 30) {
std::cout << "ConcreteHandler3 handles request " << request << std::endl;
}
else if (successor != nullptr) {
successor->handleRequest(request);
}
}
};
int main() {
ConcreteHandler1 h1;
ConcreteHandler2 h2;
ConcreteHandler3 h3;
h1.setSuccessor(&h2);
h2.setSuccessor(&h3);
h1.handleRequest(5);
h1.handleRequest(15);
h1.handleRequest(25);
return 0;
}
위의 예에서 핸들러에는 setSuccessor 메소드와 handleRequest 메소드가 있습니다. setSuccessor 메소드는 다음 핸들러 객체를 설정하고 handleRequest 메소드는 요청을 처리합니다. ConcreteHandler1, ConcreteHandler2 및 ConcreteHandler3 클래스는 각각 handleRequest 메서드를 구현합니다. 따라서 요청이 들어오면 요청을 처리할 수 있는지 확인하고, 있으면 처리하고, 그렇지 않으면 요청을 다음 처리기 개체로 전달합니다.
기본 기능은 “ConcreteHandler1”, “ConcreteHandler2” 및 “ConcreteHandler3” 개체를 생성합니다. setSuccessor 핸들러 개체를 연결하는 메서드를 호출합니다. 마지막으로 handleRequest 메서드를 호출하여 요청을 처리합니다.
C# 샘플 책임 사슬 패턴
다음은 책임 사슬 패턴의 C# 예제입니다.
using System;
abstract class Handler
{
protected Handler successor; // NEXT 처리기 객체
public void SetSuccessor(Handler next) { successor = next; }
public abstract void HandleRequest(int request);
}
class ConcreteHandler1 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 0 && request < 10)
{
Console.WriteLine("ConcreteHandler1 handles request " + request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
class ConcreteHandler2 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 10 && request < 20)
{
Console.WriteLine("ConcreteHandler2 handles request " + request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
class ConcreteHandler3 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 20 && request < 30)
{
Console.WriteLine("ConcreteHandler3 handles request " + request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
class Program
{
static void Main(string() args)
{
ConcreteHandler1 h1 = new ConcreteHandler1();
ConcreteHandler2 h2 = new ConcreteHandler2();
ConcreteHandler3 h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
h1.HandleRequest(5);
h1.HandleRequest(15);
h1.HandleRequest(25);
Console.ReadKey();
}
}
구조는 C++ 예제와 거의 동일합니다. 추상 클래스 대신 추상 키워드를 사용했습니다.
