Chain of Responsibility(체인 오브 레스포빌리티) 패턴 --------------------------------------------------------------------------------------------

  어떠한 객체를 생성하고 그 인스턴스에 인자값을 통해서 어떠한 요청을 하면 함수는 그에 대한 처리를 할 것입니다.

  하지만 인자값이 분명한데도 잘못된 객체에 집어넣거나.

  혹은 함수에 존재하는 예외처리가 되어 버리는 경우가 있습니다.

  또는 어떠한 요청에 대한 처리가 너무 많아서 하나의 클래스의 크기가 비대해 지는 경우가 있습니다.

  책임연쇄 패턴은 각종 요청에 대해서 그것을 처리할수 있는 객체가 존재할때가지 연속적으로 객체를 탐사하며 요청을 처리할수 있는 객체를 찾아주는 패턴입니다.

 

패턴적용 스토리 -----------------------------------------------------------------------------------------------

  이번에 적용되는 스토리는 다음과 같습니다.

  당신은 퀘스트시스템을 디자인하게 되었습니다.

  퀘스트 시스템에는 엘프, 오크, 휴먼의 종족이 있고 그에 대한 퀘스트를 할당하기 위한 npc가 각기 다르게 존재합니다.

  하나의 클래스를 통해서 각 요청을 처리할수 있지만 이렇게 되면 그에 따른 분기문과 코드량이 증가할게 뻔해 보입니다.

  이런때 유용하게 사용할수 있는 것이 책임연쇄 패턴입니다.

 

uml -----------------------------------------------------------------------------------------------

  

  코드를 보면 알겠지만 데코레이터 패턴처럼 마치 리스트와 같은 구조이다.

  상위의 추상클래스를 기준으로 각 책심을 연쇄시킬 객체들을 서로 연결합니다.

  만약 하나의 연결된 객체중 하나에 요청이 들어오면 자신이 처리할수 없는 요청일 경우에는 자신과 연결된 다음 객체로 다시 요청을 보냅니다.

  그렇게 요청을 연쇄하고 요청을 처리할수 있는 객체가 등장하면 그 요청을 처리하게 됩니다.

 

 

코드 -----------------------------------------------------------------------------------------------

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include "include.h"
 
enum KIND_COUNT
{    
    KIND_MAX_COUNT = 3,
    KIND_NAME_COUNT_MAX = 20, 
};
 
class CCharacter
{
private:
    char        m_szKindName[KIND_NAME_COUNT_MAX];
    char        m_szClassName[KIND_NAME_COUNT_MAX];
 
public// constructor
    CCharacter() {}
    CCharacter(char* _pKindName, char* _pClassName)
    {
        strcpy_s(m_szKindName, _pKindName);
        strcpy_s(m_szClassName, _pClassName);
    }
    ~CCharacter() {}
 
public// Set
    void SetKind(char* _pKindName)
    { strcpy_s(m_szKindName, _pKindName); }
 
    void SetClass(char* _pClassName)
    { strcpy_s(m_szClassName, _pClassName); }
 
public// Get
    char* GetKind()
    { return m_szKindName; }
 
    char* GetClass()
    { return m_szClassName; }
};
 
class QuestNpc
{
public// member parameter
    QuestNpc*            m_pQuestNpc;
    static int            m_QuestCount;
    static CCharacter*    m_Character;
 
public// constructor
    QuestNpc()
        : m_pQuestNpc(0) { }
 
    QuestNpc(QuestNpc* _pQuestNpc)
        : m_pQuestNpc(_pQuestNpc) { }
 
public// Destructor
    virtual ~QuestNpc()
    { SAFE_DELETE(m_pQuestNpc); }
 
public:
    void SetNextQuestNpc(QuestNpc* _pQuestNpc)
    { m_pQuestNpc = _pQuestNpc; }
 
public//Quest
    virtual void QuestShow()
    {
        cout << "어느 종족에도 속해있지 않은 캐릭터입니다." << endl;
        m_QuestCount = 0;
    }
    virtual void SetPlayer(CCharacter* _Character)
    {
        m_Character = _Character;
    }
 
};
 
CCharacter* QuestNpc::m_Character = NULL;
int            QuestNpc::m_QuestCount = NULL;
 
class OrcQuestNpc : public QuestNpc
{
private : // OrcQuest
    virtual void QuestShow() 
    { 
        if( !strcmp( m_Character->GetKind(), "오크" ) )
        {
            cout << "오크 퀘스트를 배분합니다." << endl;
        }
        else
        {
            ++m_QuestCount;
            m_pQuestNpc->QuestShow();
 
            switch(m_QuestCount)
            {
            case KIND_MAX_COUNT:
                QuestNpc::QuestShow();     
                break;
            }
        }
    }
};
 
class HummunQuestNpc : public QuestNpc
{
    virtual void QuestShow() // HummunQuest
    { 
        if( !strcmp( m_Character->GetKind(), "휴먼" ) )
        {
            cout << "휴먼 퀘스트를 배분합니다." << endl;
        }
        else
        {
            ++m_QuestCount;
            m_pQuestNpc->QuestShow();
 
            switch(m_QuestCount)
            {
            case KIND_MAX_COUNT:
                QuestNpc::QuestShow();     
                break;
            }
        }
    }    
};
 
class ElfQuestNpc : public QuestNpc
{
    virtual void QuestShow() // ElfQuest
    { 
        if( !strcmp( m_Character->GetKind(), "엘프" ) )
        {
            cout << "엘프 퀘스트를 배분합니다." << endl;
        }
        else
        {
            ++m_QuestCount;
            m_pQuestNpc->QuestShow();
 
            switch(m_QuestCount)
            {
            case KIND_MAX_COUNT:
                QuestNpc::QuestShow();     
                break;
            }
        }
    }    
};
 
// Chain of Resposibility.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
 
#include "stdafx.h"
#include "Chain of Resposibility.h"
 
 
int _tmain(int argc, _TCHAR* argv[])
{
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
    //_CrtSetBreakAlloc(215);
#endif
 
    CCharacter* pOrc = new CCharacter("오크""전사");
    CCharacter* pElf = new CCharacter("엘프""궁수");
    CCharacter* pHummun = new CCharacter("휴먼""마법사");
    CCharacter* pNone = new CCharacter("하플링""마법사");
    
    QuestNpc* pOrcQuestNpc = new OrcQuestNpc;
    QuestNpc* pElfQuestNpc = new HummunQuestNpc;
    QuestNpc* pHummunQuestNpc = new ElfQuestNpc;
 
    pOrcQuestNpc->SetNextQuestNpc(pElfQuestNpc);
    pElfQuestNpc->SetNextQuestNpc(pHummunQuestNpc);
    pHummunQuestNpc->SetNextQuestNpc(pOrcQuestNpc);
 
    pOrcQuestNpc->SetPlayer(pElf);
    pOrcQuestNpc->QuestShow();
    pOrcQuestNpc->SetPlayer(pOrc);
    pOrcQuestNpc->QuestShow();
    pOrcQuestNpc->SetPlayer(pHummun);
    pOrcQuestNpc->QuestShow();
    pOrcQuestNpc->SetPlayer(pNone);
    pOrcQuestNpc->QuestShow();
 
    SAFE_DELETE(pOrc);
    SAFE_DELETE(pElf);
    SAFE_DELETE(pHummun);
    SAFE_DELETE(pNone);
 
    SAFE_DELETE(pOrcQuestNpc);
    SAFE_DELETE(pElfQuestNpc);
    SAFE_DELETE(pHummunQuestNpc);
 
    return 0;
}

 

결과 ----------------------------------------------------------------------------------------------- 

 

 

Posted by JJOREG