반응형
간단한 예제로 디자인 패턴 필요성을 알아보고자 한다.
예제 코드
배열[]에서 find()로 특정 원소를 찾을 수 있다.
#include <iostream>
#include <algorithm>
using namespace std;
int* find(int* first, int* last, int v)
{
while (first != last && *first != v)
{
++first;
}
return first;
}
int main()
{
int x[10] = { 0,1,2,6,7,8,3,4,5,9 };
int* p = find(x, x + 10, 3);
cout << *p << endl; // 존재
p = find(x, x + 10, 50);
cout << *p << endl; // 존재 X
}
주어진 배열 모든 원소에서 특정 원소 x를 구한다면
이정도로 충분하지만 🙃
Q) 조건이 변하면 어떻게 될까?
ex) 짝수, 홀수, 3의 배수 등
A) 인자로 조건 함수로 받아서 처리할 수 있다.
예제 코드
#include <iostream>
#include <algorithm>
using namespace std;
int* find_if(int* first, int* last, bool(*f)(int))
{
while (first != last && f(*first) == false)
++first;
return first;
}
bool foo(int n)
{
return n % 3 == 0; // 3의 배수
}
int main()
{
int x[10] = { 1, 2, 6, 7, 8, 3, 4, 5, 9, 10 };
int* p = find_if(x, x + 10, foo);
cout << *p << endl; // 6
}
Q) 함수 포인터를 이용해서 요구사항을 만족하였다.
하지만 제한 조건이 변경되거나 전제 조건에 따라 다양한다면 어떨까?
ex) 복 없는 원소 여부, 입력받은 특정 K 배수
A) 함수 전달 방식으로는 특정 K 값을 저장할 수가 없다.
즉, 함수보다는 "상태를 저장할 수 있는 객체" 전달이 필요할 것 같다.
예제 코드
#include <iostream>
#include <algorithm>
using namespace std;
struct IPredicator
{
virtual bool valid(int n) = 0;
virtual ~IPredicator() {}
};
int* find_if(int* first, int* last, IPredicator* pred)
{
while (first != last && pred->valid(*first) == false)
++first;
return first;
}
struct IsMod : public IPredicator
{
int value;
public:
IsMod(int n) : value(n) {}
bool valid(int n) override { return n % value == 0; }
};
int main()
{
int x[10] = { 1,2,6,7,8,3,4,5,9, 10 };
int k;
cin >> k;
IsMod f(k); // 조건자 "객체" (객체이므로 "숫자 k" 상태를 가질 수 있다.)
int* p = find_if(x, x + 10, &f);
cout << *p << endl;
}
• 특정 K 배수를 찾을 수 있는 "조건자 객체" 구현
• 모든 조건자는 IPredicator 인터페이스를 구현해야 한다.
Q) 조건자 객체를 주는 것으로
모든 문제가 해결된 것일까?
A) find_if 에는 IPredicator에서 파생된 객체만 보낼수 있다. 🤷♂️
즉, 일반 함수를 사용할 수 없다.
조건자를 어떤 타입도 받을 수 있는
"템플릿 형태"로 바꾸어보자.
→ () 연산자로 호출 가능해야 한다.
→ 조건자로 "일반함수", "객체"가 모두 전달 가능하다.
예제 코드
#include <iostream>
#include <algorithm>
template<typename Pred>
int* find_if(int* first, int* last, Pred f)
{
while (first != last && f(*first) == false)
++first;
return first;
}
struct IsMod
{
int value;
public:
IsMod(int n) : value(n) {}
inline bool operator()(int n) { return n % value == 0; } // ()연산자 재정의
};
bool foo(int n) { return n % 3 == 0; }
int main()
{
int x[10] = { 1,2,6,7,8,3,4,5,9, 10 };
int k;
cin >> k;
IsMod f(k);
int* p1 = find_if(x, x + 10, f); // 객체
int* p2 = find_if(x, x + 10, foo); // 일반 함수
cout << *p1 << endl;
cout << *p2 << endl;
}
단순한 형태에서 템플릿까지
잘 알려진 디자인 패턴을 명시하지는 않았지만
리팩토링이 잘 되어있는 구조가
활용성이 좋은 것을 엿볼 수 있다.
반응형
'까망 동네 > 디자인 패턴' 카테고리의 다른 글
💻 [디자인패턴] 전략 패턴 (Strategy Pattern) (1) | 2023.10.19 |
---|---|
[디자인패턴] 싱글턴 패턴 (0) | 2023.10.14 |
MVC 패턴이란? (0) | 2022.08.28 |
팩토리 메서드 패턴 (Factory Method) (0) | 2022.07.19 |
상태 패턴 (State Pattern) (0) | 2022.05.27 |
댓글