삽질의 현장/- C++

#016_시(c)시(c)해서 C++?!_Call Me Baby ~ 콜백... (커맨드 패턴)

shovelman 2015. 7. 14. 03:59

안녕하세요 삽잡이입니다~


이번시간에는 커맨드 패턴을 통해 CallBack 기능을 느껴보려고 합니다...


커맨드 패턴이란,

객체의 행동을 별도의 클래스에 캡슐화해서 행동 객체에 확장성을 부여하는 패턴이라고 합니다...

교과서 적인 답변.... 아무도 이런 대답을 원치 않을 것이야!!!


그렇다면 예를 들어보며 callback 까지 함께 느껴보도록 하겠습니다.


이번에는 학생들의 성적기록을 저장 한 뒤에 정렬을 해보는 것으로 설명을 해보도록 하죠...

사용자가 원하는 순서대로 정렬해서 출력해볼 것입니다...

사용자가 기준을 정해두고 그 기준에 맞게 정렬해달라고 요청하면

해당되는 형태로 정렬시키려고 합니다...


우선...

'비교한다'라는 기능을 가진 가상 함수를 우선 선언해보도록 하겠습니다..


1
2
3
4
5
6
class ICompareUnit
{
public:
    virtual int CompareUnit(Unit *u1, Unit *u2) = 0;
};
 
cs


자... 두 객체를 비교하고자 하는 순수 가상함수를 만들었습니다...


다음으로 학생 클래스를 만들고 

해당 클래스에 멤버 변수에 접근 할 수 있도록 메소드를 만들어줍니다...

해당 메소드들의 기능 구현은 생략하겠습니다...


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Student
{
    string name;
    int num;
    int korea;
    int english;
    int math;
public:
    Student(string name, int num, int k, int e, int m);
    string GetName()const;
    int GetNum()const;
    int Korea()const;
    int English()const;
    int Math()const;
    void View()const;
 
};
cs


다음으로 

Student 객체들을 저장하고 정렬하고 보여줄 기능들에 대한 소스코드입니다...


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
void StuFunc::PushBack(Unit *unit)
{
    units[ucnt] = unit;
    ucnt++;
}
 
void StuFunc::Sort(ICompareUnit *ic)
{
    for (int last = ucnt; last > 1; last--)
    {
        for (int seek = 1; seek < last; seek++)
        {
            if (ic->CompareUnit(units[seek - 1], units[seek])>0)
            {
                Unit *temp = units[seek - 1];
                units[seek - 1= units[seek];
                units[seek] = temp;
            }
        }
    }
}
 
void StuFunc::List()
{
    for (int i = 0; i < ucnt; i++)
    {
        units[i]->View();
    }
}
cs


객체들을 담을 수 있도록,

정렬할 수 있도록,

그리고 보여줄 수 있도록 기능을 구현했습니다...


여기서 가장 중요한 것은 Sort() 메소드에 if문입니다...

맨 위 가상함수를 호출하고 있습니다... 코드를 더 살펴보고 이어서 설명하도록 하겠습니다..


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
class ICompareByName
    :public ICompareUnit
{
    virtual int CompareUnit(Unit *u1, Unit *u2)
    {
        string n1 = u1->GetName();
        string n2 = u2->GetName();
        return n1.compare(n2);
    }
};
 
class ICompareByNum
    :public ICompareUnit
{
    virtual int CompareUnit(Unit *u1, Unit *u2)
    {
        return u1->GetNum() - u2->GetNum();
    }
};
void main()
{
    UCol *uc = new UCol(10);
    uc->PushBack(new Unit("삽잡이"13923876));
    uc->PushBack(new Unit("삽잡삼"23451170));
    uc->PushBack(new Unit("삽잡사"33764538));
    uc->PushBack(new Unit("쌉잡이"43626211));
    uc->PushBack(new Unit("삽짭이"53157062));
    uc->PushBack(new Unit("삽삽이"63998045));
    uc->PushBack(new Unit("잡잡이"73707615));
    uc->PushBack(new Unit("쌉쌉이"83119960));
    uc->PushBack(new Unit("짭짭이"93381599));
    cout<<"정렬 전 "<<endl;
    uc->List();
    
    uc->Sort(new ICompareByName());
    cout<<"이름 순 "<<endl;
    uc->List();
 
    uc->Sort(new ICompareByNum());
    cout<<"번호 순 "<<endl;
    uc->List();
 
    delete uc;
}
 
cs


main 부분입니다...


ICompareByName 과 ICompareByNum 은 

ICompareUnit 으로 부터 파생된 클래스입니다..


즉, '비교한다'라는 기초적인 행위를 이름 비교, 숫자 비교로 확장 시킨 것이죠...


객체의 행동을 별도의 클래스에 캡슐화 한다는 것이 바로 이 뜻입니다...

각각 파생되어진 객체들은 독립적이므로 확장성에 용이해졌습니다...


아... 그리고 위의 내용을 이어서 말씀드리자면,

파생된 클래스는 기반 클래스를 통해 접근이 가능해지기때문에


if(ic->CompareUnit(units[seek-1], units[seek])>0)


해당 코드가 납득되어집니다... 즉, 어떠한 기능이 확장되더라도 

기반클래스이기 때문에 접근이 가능해진다는 것입니다...

사용자가 정의한 것을 자기 내에서 호출하고 있군요... 이 역시 callback 입니다...



이번 시간의 내용 또한...

재정리가 필요할 듯 합니다... 푸하하...

스파게티 포스팅~~~


삽잡이는 미쳐갑니다~~~~~~~~

@_@