아답터패턴 --------------------------------------------------------------------------------------------------

선생님은 말하셨다. 악마같은 패턴이하나 있는데 그중 하나가 아답터 패턴이라고.

아답터 패턴은 전혀 연관이 없는 녀석을 하나의 클래스로 만들어 새로운 클래스를 창조하거나.

두개의 연관없는 기능을 하나로 묶을 수 있다는 것이다.

즉 남의 코드를 마구 가져다 쓸때 매우 도움이 될 수도 있는 패턴이다.


아답터 클래스를 만드는 방식은 2가지가 있다.

일단 클래스 Target와 클래스 Adaptee라는 전혀 다른 기능을 가진 클래스가 있다고 치자.

(물론 하나의 애플리케이션 안에 있을 것 이므로 기본적인 목표는 동일할 수 있다.)

그런데 엮일줄 몰랐던 이 클래스들의 기능이 혼합된 새로운 기능을 만들라고 한다.

새로운 클래스를 만드는 것은 의외로 간단하다. 그냥 하나의 클래스를 만들고 두 클래스의 코드를 복사해서 붙여넣고 조정좀 해주면 되니까.

하지만 이런짓은 코드의 중복을 가져온다. 코드를 중복하지 않고 기능을 추가하거나 새로운 클래스를 만들어 낼 수는 없을까?

그걸 위한 아답터패턴이고 2가지 정도의 방법이 있다.


방법1. Adapter클래스 두개의 클래스를 상속받는다. 다중 상속이다. 하지만 상속을 통해서 adapter클래스는 두개의 클래스의 기능을 모두 사용할 수 있게 되었다. 

그러면서 다형성을 사용하여 어느 패턴의 형식으로도 관리될 수 있다.


방법2. Adapter클래스가 하나의 클래스를 상속받고 다른 클래스는 포함하게 된다. 내부에 포함된 adaptee의 함수를 사용할수 있지만 

오버라이드를 통해서 상위 클래스의 함수에 새로운 기능을 추가하는 일은 힘들다.


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

당신은 스킬을 만들라는 요청을 받았다.

그런데 여기서 웃기는 문제가 생겼다. 기존에는 공격스킬과 자신을 회복하는스킬을 나누어 놓자고 하고는 이제는 두개가 섞여있는 체력흡수라는 스킬을 만들어 내라고 한다.

즉 CATTSkill CSelfHEALSkill클래스의 스킬이 혼합된 스킬을 만들라고 하고 있다.

CMIXSkill클래스를 새롭게 만들기로 결정했다. 하지만.

코드의 중복은 피하면서 양쪽 모두의 효과를 동시에 사용할 수 있는 방법으로 아답터 패턴을 사용해보자.


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



양쪽을 모두 상속받는 CMixSkillOne과 한쪽은 상속받고 한쪽을 포함하는 CMixSkillTwo는 같은 동작을 하지만 포함과 상속이라는 약간의 차이가 있습니다.

하지만 양쪽의 인터페이스를 상속받으면서도 다른 모습을 보여줍니다.

한쪽은 인터페이스를 가상함수로 오버로딩 하고 있고.

한쪽은 새롭게 재정의 해서 사용하고 있습니다.

즉 응용하기에 따라 다양한 방법으로 혼합 합성이 가능함을 보여줍니다.



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
#pragma once
 
#include "stdafx.h"
#include "include.h"
 
typedef struct tagSkill
{
    int    iTarget;
    int    iOption;
 
    void Setting(const tagSkill& _Skill)
    {  
        *this = _Skill; 
    }
 
    void Setting(const int& _Target, const int& _Option)
    { 
        iTarget = _Target;
        iOption = _Option;
    }
 
    void tagMonster(void)
    { 
        iTarget = 0;
        iOption = 0; 
    };
 
}SKILLINFO, *PSKILLINFO;
 
class CAttSkill
{
protected:
    SKILLINFO m_SkillInfo;
 
public:
    virtual void Setting(int _Target, int _Option)
    { m_SkillInfo.Setting(_Target, _Option); }
    virtual void Setting(tagSkill& _Skill)
    { m_SkillInfo.Setting(_Skill); }
 
public:
    virtual void Effect(void)
    {
        cout << m_SkillInfo.iTarget << "번 몬스터에게 공격" << endl;
        cout << m_SkillInfo.iOption << "데미지를 입혔다." << endl;
    }
 
public:
    CAttSkill(void) {}
    ~CAttSkill(void) {}
};
 
class CSelfHealSkill
{
protected:
    int iOption;
 
public:
    virtual void Setting(const int& _Option)
    { iOption = _Option; }
 
public:
    void Effect(void)
    {
        cout << "자신에게 회복효과 적용" << endl;
        cout << iOption << "의 체력을 회복했다." << endl;
    }
 
public:
    CSelfHealSkill(void) {}
    ~CSelfHealSkill(void) {}
};
 
class CMixSkillOne
    : public CAttSkill, public CSelfHealSkill
{
public:
    virtual void Setting(const int& _iTarget, const int& _Option1, const int& _Option2)
    {
        m_SkillInfo.iTarget = _iTarget;
        m_SkillInfo.iOption = _Option1;
        iOption = _Option2;
        //Setting(iTarget, _Option1);
        //SelfSetting(_Option2);
    }
 
public:
    void Effect(void)
    {
        CAttSkill::Effect();
        CSelfHealSkill::Effect();
    }
 
 
public:
    CMixSkillOne(void) {}
    ~CMixSkillOne(void) {}
};
 
class CMixSkillTwo
    : public CAttSkill
{
private:
    CSelfHealSkill m_SelfHeal;
 
public:
    virtual void MixSetting(const int& _iTarget, const int& _Option1, const int& _Option2)
    {
        m_SkillInfo.iTarget = _iTarget;
        m_SkillInfo.iOption = _Option1;
        m_SelfHeal.Setting(_Option2);
    }
 
public:
    void MixEffect(void)
    {
        Effect();
        m_SelfHeal.Effect();
    }
 
public:
    CMixSkillTwo(void) {}
    ~CMixSkillTwo(void) {}
};
 
// Adapter.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
 
#include "stdafx.h"
#include "Adapter.h"
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    int Target = 0;
    int Option = 10;
 
    cout << "************ AttSkill ************" << endl;
 
    CAttSkill AttSkill;
    AttSkill.Setting(Target, Option);
    AttSkill.Effect();
 
    cout << "************ SelfHealSkill ************" << endl;
 
    CSelfHealSkill SelfHeal;
    SelfHeal.Setting(Option);
    SelfHeal.Effect();
 
    cout << "************ MixSkillOne ************" << endl;
 
    CMixSkillOne MixSkillOne;
 
    MixSkillOne.Setting(Target, Option, Option);
    MixSkillOne.Effect();
 
    cout << "************ MixSkillTwo ************" << endl;
 
    CMixSkillTwo MixSkillTwo;
 
    MixSkillTwo.MixSetting(Target, Option, Option);
    MixSkillTwo.MixEffect();
 
    return 0;
}


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




'게임개발공부 > 디자인패턴' 카테고리의 다른 글

구조패턴 <브릿지 패턴> (가교)  (0) 2013.12.23
uml 관계도 좀더 명확히  (1) 2013.12.22
메인프레임 작업 01  (0) 2013.12.21
생성패턴 <싱글톤 패턴>  (0) 2013.12.18
생성패턴 <프로토 타입>  (0) 2013.12.17
Posted by JJOREG