(book summary)GoF Design Pattern
simuruk wiki
목차
책
- 저자 Gang of Four
디자인 패턴이란
- 때에 따라 때려 맞추는 ad hoc(특별한 목적을 위해서라는 라틴어)해결책보다 좀더 수고를 해여 유연성과 재사용성을 얻을수 있다
- 설계자들이 이미 경험한 소프트웨어 설계의 경험을 기록 해놓아 설계를 그대로 적용(재사용)할수 있다
- 특정한 전후 관계에서 일반적 설계 문제를 해결하기 위해 상호교류하는 수정 가능한 객체와 클래스들에 대한 설명입니다
- 구체적인 설계나 구현을 설명하지 않고 추상화를 갖는 패턴까지 설명합니다
디자인 패턴 4가지 요소
- Pattern name 패턴이름은 한두 단어로 설계 문제와 해법을 서술해야한다
- Problem 문제는 언제 패턴을 사용하는지 해결할 문제와 그 배경을 설명합니다
- Solution 해법은 설계를 구성하는 요소들과 그 요소들 간의 관계, 책임 그리고 협력 관계를 서술합니다
- Consequence 결과는 디자인 패턴을 적용해서 얻는 결과와 장단점을 서술합니다
- 비용과 효과를 측정하여 디자인패턴을 선택하기 때문에 가장 중요한 부분입니다
- 재사용성도 중요한 요소로 시스템의 유연성, 확장성, 이식성등에 커다란 영향을 줍니다
사례
Creational(생성)
- 추상 팩토리
- 빌더
- 팩토리 메서드
- 프로토타입
싱글턴
멀티스레드 개발에서 일관성을 보장해주는 방식
- 생성자 막기
- 소멸자 막기
- getter
- multithread
// C++
Foo* Foo::Instance() {
if(pinstance == nullptr) {
lock_guard<mutex> lock(m_);
if(pinstance == nullptr) {
pinstance = new Foo();
}
}
return pinstance;
}
// JAVA
public static synchronized singleton getInstance () {
if (instance == null)
instance = new ThreadSafeInitalization();
return instance;
}
접기 1. 주소 값을 이용한 방식
class yh_singleton
{
public:
static yh_singleton& getInstanse(){
static yh_singleton instance;
return instance;
};
int num;
private:
yh_singleton(){};
yh_singleton(const yh_singleton& other);
yh_singleton& operator=(yh_singleton& cls);
~yh_singleton(){};
};
yh_singleton& yh= yh_singleton::getInstanse();
yh.num= 4;
2. 포인터를 이용한 방식
class yh_singleton
{
public:
static yh_singleton* getInstanse(){
static yh_singleton instance;
return &instance;
};
int num;
private:
yh_singleton(){};
yh_singleton(const yh_singleton& other);
yh_singleton& operator=(yh_singleton& cls);
~yh_singleton(){};
};
yh_singleton* yh= yh_singleton::getInstanse();
yh->;num= 4;
3. 템플릿 싱글톤
template <typename T>
class yh_singleton
{
public:
static T* getInstance()
{
if (instance == NULL)
instance = new T;
return instance;
};
static void destroyInstance()
{
if (instance)
{
delete instance;
instance = NULL;
}
};
private:
static T* instance;
protected:
yh_singleton(const yh_singleton& other);
yh_singleton& operator=(yh_singleton& cls);
yh_singleton();
virtual ~yh_singleton(){};
};
template <typename T>T * yh_singleton<T>::instance = NULL;
class ojectA : public yh_singleton<ojectA>
{
public:
ojectA();
~ojectA();
int a;
};
Structural(구조)
- 어뎁터
- 브릿지
- 컴포지트
- 데코레이터
- 퍼사드
- 플라이 웨이트
- 프록시
Behavioral(행동)
- 체인 오브 리스판시빌리티
- 코맨드
- 인터프리터
- 이터레이터
- 메디에이터
- 메멘토
- 옵저버
- 스테이트
스트레티지
참고
- is-a보다 has-a가 좋을수 있다
- 상속 보다는 구성을 활용한다
의도
- 동일 계열 알고리즘군을 정의하고 각각을 캡슐화하여 상호 교환해서 사용할 수 있도록 합니다
- 알고리즘을 사용하는 클라이언트와 상관없이 독립적으로 알고리즘을 변경할 수 있게 합니다
동기
- 알고리즘 코드가 분리가 되어있지 않다면 클래스가 복잡해진다
- 때에 따라서 알고리즘이 다르기 때문에 변경이 어렵다
- 새로운 알고리즘을 추가하거나 기존의 것을 다양화하기가 어렵다
- 이런 캡슐화된 알고리즘을 전략이라고 합니다
활용성
- 많은 행동중 하나를 가진 클래스를 구성할 수 있는 방법을 제공합니다
- 알고리즘의 변형이 필요할때 변경할수 있습니다
- 사용자가 몰라야 하는 알고리즘이 있을때 전략 클래스에만 두면 되므로 사용자가 몰라도 됩니다
- 하나의 클래스가 많은 행동을 정의하고, 이런 행동이 다중 조건문의 모습을 취할때 각각을 전략 클래스로 옭겨놓는 것이 좋습니다
참여자
- 스트레티지(컴포지터): 알고리즘 인터페이스
- 컨크리트 스트레티지: 실제 알고리즘
- 컨택스트(컴포지션): 전락에 대한 참조자 관리, 스트레티지의 서브클래스 인스턴스를 갖고 있음으로 구체화합니다
결과
- 동일 계열의 관련 알고리즘군이 생깁니다, 재사용도 가능합니다
- 서브클래싱을 사용하지 않는 대안입니다, 알고리즘을 변형, 이해, 확장이 쉽습니다
- 조건문을 없앨 수 있습니다
- 구현의 선택이 가능합니다, 전략중 하나를 선택하여 사용합니다
- 사용자(프로그램)는 서로 다른 전략을 알아야 합니다
- 전략 객체와 컴포지션 객체 사이에 의사소통 오버헤드가 있습니다, 사용되지 않는 매개변수를 컴포지션이 떠안아야합니다
- 객체 수가 증가합니다, 플라이웨이트를 사용하면 좋습니다
- 템플릿 메서드
- 비지터