공통성과 가변성의 분리

EHminShoov2J·2024년 10월 6일
0

Design Pattern

목록 보기
2/6
post-thumbnail

1. Template method

1.1. 정의

  • 오퍼레이션에는 알고리즘의 처리 과정만을 정의 하고 각 단계에서 수행할 구체적인 처리는 서브 클래스에서 정의
  • 의도 : 알고리즘의 처리과정은 변경하지 않고 알고리즘 각 단계의 처리를 서브클래스에서 재정의 할 수 있게 한다.
  • 탬플릿이란 전체적인 틀을 의미함.

1.2. 적용법

  • 변하지 않는 코드 내부의 변경될 수 있는 코드를 찾는다
  • 변해야 하는 코드를 가상함수로 분리
  • 변경이 필요한 부분을 재정의 해서 활용.

클래스 다이어그램

2. Strategy Pattern

2.1. 정의

  • 다양한 알고리즘들이 존재하면 이들 각각을 하나의 클래스로 캡슐화 하여 알고리즘 대체가 가능하도록 구현 (이를 통해 알고리즘을 변경하더라도 클라이언트는 아무런 변경을 할 필요가 없음)

2.2 적용 방법

  • 인터페이스를 만들고, 약한 결합 을 통해 생성한 정책 클래스의 객체를 호출하여 활용
int main()
{
	Edit edit;
	DigitValidator v(5); // 정책 클래스 객체 생성
	edit.set_validator(&v); // 정책 클래스의 객체 호출

//	AddressValidator v2(15); // 또다른 정책을 미리 생성해서 사용하는 것도 가능
//	edit.set_validator(&v2);

	while (1)
	{
		std::string s = edit.get_text();
		std::cout << s << std::endl;
	}
}

2.3. Strategy VS Template pattern

  • Strategy

    • 정책을 사용하는 클래스와 정책이 서로다른 클래스로 분리 (위임)
    • 정책을 필요로 하는 다른 클래스에서도 동일한 정책 사용 가능
    • 실행시간에 전략 변경 가능
  • Template pattern

    • 탬플릿 패턴을 사용하는 경우 정책을 사용하는 클래스가 해당 정책을 소유
    • 다른 클래스에서 해당 정책을 사용할 수 없음
    • 실행시간에 정책 변경 불가능 (정책을 사용하는 새로운 클래스를 호출해야 함)
    • 다른 클래스에서 사용할 일이 없고, 실행시간중 교체할 이유도 없는 경우(Draw 함수와 같이) 가상함수로 구현하는 경우, 맴버 데이터 접근도 편리 하다는 이점 또한 존재.
  • 변경되는 부분이 공용성이 있는지, 종속적인 것인지, 맴버변수에 접근이 필요한지 등을 종합적으로 고려하여 선택


    클래스 다이어그램

3. Policy Base Design

3.1. 정의

  • 클래스의 동작을 다양한 정책 클래스로 분리하여 템플릿 인자로 전달 하고, 컴파일 타임에 조합함으로써 유연하고 효율적인 설계를 가능하게 하는 템플릿 메타프로그래밍 기법으로 런타임 오버헤드 없이 구현 가능.(CPP의 STL이 해당 방식을 차용)

템플릿 : 모든 데이터 유형과 작동할 수 있는 함수 또는 클래슬 생성하기 위한 틀

// Function template to swap two values
template <typename T>
void swapValues(T& a, T& b) {
   T temp = a;
   a = b;
   b = temp;
}

템플릿 메타 프로그래밍 : 런타임 대신 컴파일 타임에 코드를 생성, 런타임에 직접 적용

template <typename T>
T multiply(T a, T b) {
   return a * b;
}

int result = multiply<int>(3, 4);  // Compiler generates a version where T=int

//-------------------------------------
// 컴파일 시간에 생성되는 int version multiply
int multiply(int a, int b) {
   return a * b;
}
//---------------------------------------

3.2. Strategy VS Policy base design

  • Strategy pattern
    • 전략 패턴의 경우 인터페이스를 사용하여 전략 객체를 생성하고 객체를 전달 받음
    • 해당 과정에서 가상함수 테이블을 사용하기에 런타임에 오버헤드가 발생할 수 있음
  • Policy base design
    • 전략 패턴과 개념은 유사하지만, 객체 대신 템플릿 인자를 활용하여 정책을 전달하기 때문에 런타임 오버헤드가 없음
    • 인라인 치환도 가능
    • 실행시간에 교체 불가능
    • 인터페이스가 없기 때문에 구현자가 반드시 규칙에 맞추어 모든 기능을 수행할 수 있도록 구현 해야 함

3.3. 예시 코드

template<typename T, typename Ax = std::allocator<T> > // 기본 Allocator 제공
class vector
{
	T* ptr;
	Ax ax;
pubilc:
	void resize(std::size_t newsize)
	{
		ptr = ax.allocate(size);

		ax.deallocate(ptr, size);
	}
};

template<typename T>
class malloc_allocator 
{
public:
//반드시 구현자가 아래의 두 함수를 구현해 주어야 함. 인터페이스가 없으므로 에러가 발생하지 않음. 문서에 맞게 구현자가 구현.
	inline T*   allocate(std::size_t size)  { return static_cast<T*>(malloc(sizeof(T)*size));}
	inline void deallocate(T* ptr, std::size_t size) { free(ptr);}
};

int main()
{
	vector<int, malloc_allocator<int> > v;
}

0개의 댓글