본문 바로가기

개발/디자인패턴

구조 개선을 위한 디자인패턴

 장세찬, 『GoF 디자인 패턴! 이렇게 활용한다. : C++로 배우는 패턴의 이해와 활용』, 한빛미디어(2004)
책의 내용을 배끼기보단 제가 이해한 내용을 위주로 작성해서 틀린 부분이 있을 수 있습니다!


1. Adapter 패턴

Adapter 패턴은 이미 개발된 API를 제 코드의 인터페이스에 맞게 사용하기 위한 패턴입니다.
세상엔 훌륭한 API가 많이 개발되어있죠. 하지만 그 API의 인터페이스(함수 명, 파라미터 등)는 제 코드와 맞지 않는 경우가 많습니다.
이럴 때, API는 사용하되 인터페이스를 맞추기 위한 코드가 바로 Adapter 패턴입니다.

1) Object Adapter
새로 정의한 클래스에 멤버변수로 API에서 사용하는 클래스 객체를 사용하는 방법입니다.
저는 말보단 코드로 설명하는게 빠른 것 같네요...

class A {
	A();
	virtual ~A();

	API object;
};


이렇게 멤버변수로 정의해서 사용하는 방식입니다.

2) Class Adapter
Class Adapter방식은 API에서 사용하는 클래스를 상속받아서 쓰는 방식입니다.

class A : public API {
	A();
	virtual ~A();
}

이렇게 API 클래스를 상속받아서 멤버 변수 정의 없이 사용할 수 있다는 장점이 있습니다.

2. Bridge 패턴

클래스의 상속은 어떤 기능을 특정 기준에 따라 구분해서 구현해야할 때 사용합니다.
가령, sendMessage(string sMsg) 함수를 sms, email 두 가지로 나눠서 구현해야 하는 경우 사용하죠.

하지만 만약 클래스를 인터페이스 기준과 구현 기준, 즉 2가지 기준으로 구분해야 하는 경우엔 어떻게 해야할까요?
sendMessage함수를 sms, email로도 나눠야하고 모바일, PC로도 나눠야 한다고 가정해보겠습니다.
그럼 sms,email은 인터페이스, 모바일과 PC는 구현부가 되겠네요.
이럴 때 사용하는 것이 Bridge 패턴입니다.

class A {
	virtual bool func(int i);
	virtual bool func(char c);
}

class A_1 : A {
	bool func(int i) {
		// function context
		return true;
	}
}

class A_2 : A {
	bool func(char c) {
		// function context
		return true;
	}
}

class B {
public:
	A *getVal() {
		if ( NULL == m_val ) {
			setVal();
		}
		return m_val;
	}
	virtual void doSomething();
private:
	void setVal() {
		if ( /* case 1 */ ) {
			val = new A_1;
		}
		else if ( /* case 2 */ ) {
			val  = new A_2;
		}
	}

private:
	A *m_val;
}

class B_1 : B {
	void doSomething() }
		// do something with m_val
	}
}

class B_2 : B {
	void doSomething() }
		// do something with m_val
	}
}

int main() {
	B_1 val;
	val.doSomething();
}


예제 코드를 간략하게 구현하면 이렇게 될 것 같네요.
main에서는 클래스 B만 구분해서 B_1이나 B_2를 사용합니다.
그리고 A를 어떻게 구분할지는 B에서 알아서 해주는거죠
사용자와 구현부(class A)를 이어주는 브릿지(class B)역할을 하는거죠.

3. Composite 패턴

클래스는 다른 클래스의 객체를 멤버변수로 사용할 수 있습니다. 즉, 여러 클래스의 객체로 구성된 클래스를 만들 수 있다는 의미입니다.
이때, 클래스를 구성하는 다른 객체들이 자기 자신이 상속하고 있는 부모클래스인 경우, 이를 Composite 패턴이라고 합니다.
이어서 설명하고 싶지만 예제코드를 보는게 낫겠죠?

class A {
	virtual bool func(int i);
	virtual bool func(char c);
}

class A_1 : A {
	bool func(int i) {
		// function context
		return true;
	}

	std::vector<A *> m_list;
}

class A_2 : A {
	bool func(char c) {
		// function context
		return true;
	}
    
private:
	std::vector<A *> m_list;
}


이렇게 동적으로 객체를 만들어내는 형태의 디자인 패턴입니다.
이런 패턴은 어떨 때 쓰는걸까요?

보통은 예제에 있는 것처럼 여러 A클래스를 조합한 하나의 A클래스를 만들 때 사용해요.
예를 들어, PPT에서 여러 도형을 그룹으로 묶어 하나의 도형으로 사용하기도 하죠? 이런 경우에 사용하는게 바로 Composite 패턴입니다.



출처: https://jaduwvad.tistory.com/149 [Jadu Diary]

4. Decorator 패턴

이건 음... 이해도 못하겠고 왜 쓰는지도 잘 모르겠어서...
Todo로 두고 더 공부해서 써야겠네요



'개발 > 디자인패턴' 카테고리의 다른 글

구조 개선을 위한 디자인패턴(2)  (1) 2020.12.10
객체 생성 관련 디자인패턴  (0) 2020.11.21