Chain of Responsibility 패턴이란?
Chain of Responsibility 패턴은 객체의 처리를 연속적으로 연결된 처리기(Handler) 객체들로 전달하고, 이를 통해 요청을 처리하는 패턴입니다. 즉, 객체가 어떤 처리를 해야 할 때 그 처리를 담당하는 객체를 직접 호출하는 것이 아니라, 요청을 받은 객체가 체인 안에서 다음 객체에게 요청을 전달하는 방식으로 처리합니다. 또한, 처리기 객체들을 동적으로 추가하거나 삭제할 수 있어서 처리기 객체를 추가하거나 석제 하는 것만으로도 프로그램의 동작을 변경할 수 있습니다.
Chain of Responsibility 패턴 구성 요소
이 패턴은 일반적으로 다음과 같은 구성 요소로 이루어져 있습니다.
- Handler 인터페이스 또는 추상 클래스 : 처리기 객체들이 구현해야 하는 메서드를 정의합니다. 이 인터페이스나 추상 클래스는 다음 처리기 객체를 설정하는 메서드와 요청을 처리하는 메서드를 포함합니다.
- ConcreteHandler 클래스 : 실제 처리를 담당하는 객체입니다. 이 클래스는 Handler 인터페이스나 추상 클래스를 구현합니다.
- Client : 처리기 객체들을 연결하여 요청을 처리하는 객체입니다. 이 객체는 처리기 객체들을 연결하는 체인을 설정하고, 요청을 보내는 역할을 합니다.
클래스 다이어 그램
다음은 Chain of Responsibility 패턴의 클래스 다이어그램입니다.
위 다이어 그램에서 Handler는 추상 클래스 또는 인터페이스로 처리기 객체들이 구현해야 하는 메서드를 정의합니다. ConcreteHandler1, ConcreteHandler2, ConcreteHandler3 클래스는 실제 처리를 담당하는 객체로서 Handler 클래스를 상속받아 handleRequest 메서드를 구현합니다.
Chain of Responsibility 패턴의 C++ 예제
다음은 Chain of Responsibility 패턴의 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;
}
위 예제에서 Handler는 setSuccessor 메서드와 handleRequest 메서드를 갖습니다. setSuccessor 메서드는 다음 처리기 객체를 설정하고, handleRequest 메서드는 요청을 처리합니다. ConcreteHandler1, ConcreteHandler2, ConcreteHandler3 클래스는 각각 handleRequest 메서드를 구현하여 요청이 들어오면 해당 요청을 처리할 수 있는지 검사하고, 처리할 수 있다면 처리하고, 그렇지 않으면 그다음 핸들러 객체에 요청을 전달합니다.
main 함수에서는 ConcreteHandler1, ConcreteHandler2, ConcreteHandler3 객체를 생성하고, setSuccessor 메서드를 호출하여 처리기 객체들을 체인으로 연결합니다. 마지막으로 handleRequest 메서드를 호출하여 요청을 처리하도록 합니다.
Chain of Responsibility 패턴의 C# 예제
다음은 Chain of Responsibility 패턴의 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++ 예제와 거의 동일합니다. 추상 클래스 대신 abstract 키워드를 사용했습니다.
댓글