본문 바로가기
까망 동네/디자인 패턴

[프로그래밍] 디자인 패턴 필요성

by 까망 하르방 2022. 8. 29.
반응형

간단한 예제로 디자인 패턴 필요성을 알아보고자 한다.

📌 디자인 패턴(Design Pattern)이란?

 

💻 디자인 패턴(Design Pattern)이란?

👨‍💻 디자인 패턴(Design Pattern)이란? • SW 개발 방법 중에서도 구조적인 문제 해결에 목적을 둔다. • 알고리즘과 같이 특정 문제를 해결하는 Logic 형태보다는    특정 상황에 적용할 수 있

zoosso.tistory.com


 

예제 코드

배열[]에서 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;
}

 

단순한 형태에서 템플릿까지

잘 알려진 디자인 패턴을 명시하지는 않았지만

 

리팩토링이 잘 되어있는 구조가

활용성이 좋은 것을 엿볼 수 있다.

반응형

댓글