안녕하세요 삽잡이입니다...
몇일 전에 커맨드 패턴, 그러니까 명령어 패턴에 대한 글을 올린 기억이 납니다...
헷갈리니까... 다시한번... 예제를 통해 살펴보도록 하겠습니다...
전체적인 코드보다는 이럴 때 사용하는 구나 하는 감을 잡기 위해... 부분적으로...
시작합니다...
우선...
멤버 하나하나를 담는 Unit이라는 class가 있다고 생각해봅시다...
이 Unit을 관리하는 UnitCollection 이라는 class를 만들어보도록 하죠...
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 | #pragma once #include <vector> #include "Unit.h" using namespace std; class IIsEqual { public: virtual bool operator()(Unit *unit) = 0; }; class ICompare { public: virtual int operator()(Unit *u1, Unit *u2) = 0; }; class UnitCollection : private vector<Unit *> { public: void AddUnit(Unit *unit); Unit *Find(IIsEqual &ise); void Sort(ICompare &com); void List(); }; | cs |
그 중에서도 함수 호출에 대한 오버로딩 함수를 정의했습니다.
이를 파생하는 클래스는 반드시 이에 대한 구현을 해야합니다.
그 아래 UnitCollection 클래스를 살펴본다면 vector 의 기능 중
전체가 아닌 사용자에 입맛에 맞는 부분만을 사용하기 위해 맞춤형으로 메소드들을 구현했습니다.
또 여기서 Find와 Sort 메소드를 보시면 아시겠지만,
모두 추상 메소드형의 인자를 받고 있습니다.
해당 메소드의 내용을 살펴보도록 하겠습니다...
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 | Unit *UnitCollection::Find(IIsEqual &ise) { UIter seek = begin(); UIter last = end(); Unit *unit = 0; for (; seek != last; ++seek) { if (ise(*seek)) { unit = *seek; break; } } return unit; } void UnitCollection::Sort(ICompare &com) { UnitCollection &na = (*this); for (int n = size(); n > 1; n--) { for (int i = 1; i < n; i++) { Unit *temp = na[i - 1]; na[i - 1] = na[i]; na[i] = temp; } } } | cs |
다시 한번 말씀드리지만 모두 추상 메소드 형식의 인자를 받고 있습니다.
그리고 주목해야할 점은 바로
if(ise(*seek))과 같이 사전에 구현한 함수호출 오버로딩에 의해서 자신을 불렀던 곳으로
다시 callback을 하는 것을 확인할 수 있습니다.
이처럼 공통적인 기능만을 구현해 두고 인자를 기반 클래스로 받는다면
효율적이며 해당 소스파일 자체가 가벼워질 수 있습니다....
어떤말인지 이해가 가시지 않는다면 아래의 코드를 참고하시길 바랍니다.
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 | class EqualNum :public IIsEqual { int num; public: EqualNum(int num) { this->num = num; } virtual bool operator()(Unit *unit) { return unit->GetNum() == num; } }; void App::FindByNum() { int num = 0; cout << "번호:"; cin >> num; EqualNum en(num); Unit *unit = uc->Find(en); if (unit == 0) { cout << "존재하지 않음" << endl; return; } unit->View(); } | cs |
검색 기능과 정렬 기능을 가진 메소드들을 사전에 정의 해뒀습니다.
그리고 실제로 application 파일에서 이와 같은 기능을 호출해서 사용하려고 할 때
각각 검색하는 방법, 조건들이 다양할 수 있습니다.
이때 커멘드 패턴의 빛이 발휘되는 것입니다...
사용하는 기능마다 일일히 정의할 필요 없이
사전에 만든 IIsEqual, ICompare 과 같은 기반 클래스를 만들어 놓고
입맛에 맞게 파생 클래스로 다양한 조건들에 충족하는 클래스를 만드는 것입니다.
그렇다면 바로 위의 코드 중 Find(en) 처럼 메소드 호출을 통해
기반 클래스 형식으로 인자를 보냈어도
결국에는 Find 메소드에서 Callback을 함으로 조건에 충족하는
결과를 수행할 수 있게 됩니다.
이와 같이 커맨드 패턴을 기반으로한 코드를 구현한다면
기반이 되는 기능으로 부터 여러 조건에 맞게 파생 클래스로 기능을 구현하여
재사용성을 높여 프로그램을 만들 수 있습니다.
위와 같이 IIsEqual, ICompare 처럼 기반이 되는 기능을 사전에 약속해두고
필요한 조건들에 맞게 파생클래스를 만든다는 것이죠...
지금껏 이 글을 읽으셨다면 아시겠지만
Find, Sort 메소드는 건들지도 않았습니다. 단지 조건에 맞는 파생 클래스만 구현하고
해당 메소드를 만들어 호출했을 뿐입니다...
이렇게 재사용할 수 있고, 기능 구현한 코드 또한 복잡하지 않고
간결하게 사용할 수 있어 메리트가 있군요...
객체지향이라는 세계는 참으로 오묘하고도
매력이 있는 세계 같습니다...
최근에 C언어를 사용할 일이 있어서 코딩을 하고 있었는데
확실히 C++에 손을 대다가 갑자기 C를 만지니 DownGrade 된듯한 느낌을 ㅎㅎ...
절차지향에 대한 개념을 무시하는 것은 아니지만
객체지향에 대한 편리함을 새삼 느끼는 시간이었습니다...
다음시간에 더욱 알찬 내용으로 찾아 뵙도록 하죠!
이상 삽잡이였습니다~!
'삽질의 현장 > - C++' 카테고리의 다른 글
#023_시(c)시(c)해서 C++?!_ 레퍼런스형 의 이해 (0) | 2015.07.20 |
---|---|
#022_시(c)시(c)해서 C++?!_ 팩토리 패턴 사용해보기 (0) | 2015.07.20 |
#020_시(c)시(c)해서 C++?!_ 되돌아보자 씨쁠쁠 ... (0) | 2015.07.18 |
#019_시(c)시(c)해서 C++?!_STL_vector 기능 구현 코드 (0) | 2015.07.16 |
#018_시(c)시(c)해서 C++?!_STL_Vector 예제 (0) | 2015.07.15 |