삽질의 현장/- C++

#015_시(c)시(c)해서 C++?!_Call Me Baby ~ 콜백... (옵저버 패턴)

shovelman 2015. 7. 14. 03:47

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


이번시간에는 옵저버 패턴을 사용하여 콜백기능을 확인해보려고합니다...


우선, 콜백에 대해서 알아보도록 하겠습니다...

CallBack.... 콜백이란...

기존의 main 메서드 즉, 주 객체가 종된 객체들을 호출하던 것과 반대로

종된 객체가 주된 객체에게 호출을 던지는 것을 합니다...


우리가 필요에 의해서 main 메서드에서 여러 함수들을 호출을 했었는데요

이번에는 여러 함수들에서 주된 객체인 main을 호출한다는 것입니다...

정리해서 말씀드리자면,

OS에 의해서 개발자가 정의한 함수를 호출하는 것을 콜백이라고 말하는 것입니다...


예를 들자면, 대표적으로 윈도우 프로그래밍이 있죠...

우리가 사용하는 윈도우 OS에서 마우스 돌리고, 키보드 누르는 등...

모든 행동 하나하나를 할 때마다 이와 같은 이벤트에 대해 모니터링을 하지 않습니다...


각 사건... 그러니까 마우스 돌리고 키보드 누르는... 

그런 사건들이 발생한다면 해당 함수를 호출해달라고 OS에 등록을 하는 것입니다.

그렇게 등록을 하고 나면, 

사건 감지시에 윈도우 OS는 해당 윈도우에게 사건이 발생했다고

callback 하며 알려주게 되는것입니다...

자세한것은 윈도우 프로그래밍을 할때... 하하...



아무튼...

이 CallBack에 대해서 코드를 작성해보며 감을 익혀 보려고 하는데요...

지금 이 글에서는 출판과 구독 패턴이라고 부르는 

옵저버 패턴을 통해서 감을 잡아보시죠...


옵저버 패턴은 

정보가 변경되었을 때 다른 객체들에게 알리며 

변경된 정보를 즉각적으로 반영할 수 있는 방법입니다...


객체의 정보들을 가지고 있는 서브젝트(Subject)와 

정보 객체를 참조하는 옵저버(Observer)로 나눠지는 패턴입니다...


간략하게 옵저버 패턴을 사용한 코드에 대해 설명을 드리자면,


삽잡이 인력소로부터 A 현장, B 현장, C 현장 으로 

오고 가는 일꾼들에 대해서 콜백을 표현해보려고 합니다...

음... 소개하려는 코드가 엉뚱하군요...


1
2
3
4
5
class IComeBack
{
public:
    virtual void ComeBack(Unit *unit) = 0;
};
cs


이와 같이 가상함수를 통해 일꾼들이 오갈 수 있는 옵저버 인터페이스를 만듭니다.

다음 main인 삽잡이 인력소에서는 생성자를 만들 때

공장으로 갈 인원들에 대한 리스트와 현장 A, B, C에 대해 생성을 해야합니다...


1
2
3
4
5
6
7
8
9
10
11
12
SAP::SAP(void)
{
    cout<<"최대 관리 일꾼 수:"<<endl;
    최대값 = 일꾼 수를 입력받는다;
    일꾼 = new Unit*[최대값];
    ucnt = 0;
    for(int i = 0; i<3; i++)
    {
        현장[i] = new Place(최대값);
        현장[i]->RegIComeBack(this);
    }
}
cs


일꾼 수를 입력 받고 그 받은 변수만큼의 new 키워드를 통해 객체를 생성합니다.

그리고, 각각 현장에서도 최대 인원을 수용할 수 있을 만큼의 크기로 객체를 생성합니다.

여기서 중요한것은 RegIComeBack() 메소드입니다...

우선 살펴보도록 하겠습니다...


1
2
3
4
void 현장::RegIComeBack(IComeBack *icb)
{
    this->icb = icb;
}
cs


현장 클래스에서 복귀할 곳을 등록하는 것입니다...

이때 위의 SAP 생성자에서는 일꾼들이 

현장 A, B, C에 갔다가 호출시 SAP 인력소로 오도록 하게끔 각 A, B, C 현장에 등록을 한 것입니다.


현장에서는 SAP 인력소를 알 수 없습니다. 

왜냐, 알게되면 SAP 인력소에 있는 변수 및 메소드들을 호출할 위험이 있어서 

꼬일 수 있는 문제가 발생할 가능성이 있기 때문이죠...

하지만 일꾼들을 되돌릴 수 있어야 되지 않습니까... 평생 일만 하다가는... 흙...


따라서 일터는 IComBack 이라는 인터페이스를 참조하게 되고

구현 약속만 한 IComBack 인터페이스를 통해 

IComBack에서 파생된 SAP 인력소에 알려줄 수 있게 되는 것입니다...


이렇게 자기 자신을 등록한다면 

IComeBack을 참조하지만 실질적으로는 SAP 인력소의 IComeBack이 호출 되게 됩니다.

IComeBack 인터페이스는 순수 가상 함수로 이루어져 있기 때문에

파생 클래스인 SAP 인력소에서 IComeBack 기능이 가능하도록 구현됩니다. 


결국 현장에서는 SAP 인력소 IComeBack 기능을 호출하는 꼴이 되는 것입니다...

이를 CallBack이라고 볼 수 있는 것이구요...

(출판과 구독의 관점에서 보면 SAP 인력소는 구독자 현장은 출판사라고 할 수 있겠네요...)


아무튼...

일꾼들을 SAP 인력소에서 등록을 완료하고 난뒤에,


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
void SAP::MoveUnit()
{
    Unit *unit = 0;
    cout<<"이동할 일꾼 이름:"<<endl;
    name = 일꾼 이름 입력받고
 
    for(int i = 0; i<ucnt; i++)
    {
        if(units[i]-> 이름과 같은지 확인)
        {
            unit = units[i];
            break;
        }
    }
    if(unit == 0)
    {
        cout<<"잘못 선택하였습니다."<<endl;
        return;
    }
    현장 *place = 0;
    place = SelectPlace();
    if(place)
    {
        현재 SAP 인력소에 명단에서 제외하고;
        해당 장소로 유닛을 보낸다;
    }
    else
    {
        cout<<"잘못 선택하였습니다."<<endl;
    }
}
cs


이와 같이 보낼 일꾼과 현장을 을 입력받고 해당 일꾼을 해당 현장으로 보내는 것입니다.

이때 현장으로 가는 일꾼은 SAP 인력소에서 제외해야하기에 없애야합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void 현장::ComeBack()
{
    Unit *unit = 0;
    unit = SelectUnit();
    if(unit)
    {
        if(icb)
        {
            현재 현장 명단에서 제외하고;
            SAP 인력소로 ComeBack 시킨다;
        }
        else
        {
            cout<<"복귀할 장소가 없음"<<endl;
        }
    }
    else
    {
        cout<<"잘못 선택하였습니다."<<endl;
    }
}
cs


반대로 현장에서도 인력소로 복귀 시킬 수 있습니다.

이때에는 SAP 인력소를 생성하며 RegIComeBack() 에 SAP 인력소 위치를 등록했기 때문에

자연스럽게 해당 인력소로 복귀할 수 있게됩니다.


일꾼들은 SAP 인력소에 저장되어 있었습니다.

그리고 각 현장으로 갈 떄와 복귀할때 모든 변경사항이 발생시

즉각적으로 반영할 수 있는것을 확인할 수 있었습니다.


이와 같은 패턴을 옵저버 패턴이라고 합니다...

또한 ComeBack 이라는 가상 함수를 인력소와 현장에서 오버라이딩하여 사용했고,

결과적으로 복귀를 원할 시 종된 객체에서 호출을 하는 Callback 기능 또한 확인 할 수 있었습니다...

즉, 사용자가 정의한 ComeBack을 자기 내에서 호출하는 것을 확인 할 수 있었던 것이죠...

이를 callback이라고 하는것이고요



물론.... 

지금 제가 봐도 뭔말인지 못알아 볼 거 같습니다...

주말에 말끔하게 정리를 해야할 거 같습니다...

하루하루 배운 것들에 대해 정리하려고 하지만 힘들군요....

내가 볼땐 이해가지만... 3자의 입장에서는 x소리로 보일듯 합니다 ㅠㅠ


소스코드만 스파게티가 아닌... 글 또한 스파게티가 되고 있군....


시간날때 정리를...