프로그래밍/C++ 이용한 디자인패턴

Birdge(브릿지) 패턴 with C++

친루엄 2018. 4. 9. 20:38

[ Birdge 패턴이란.]

클래스 구조를 정의함에 있어 외부에 공개되는 인터페이스 및 그에 따른 논리적 관점의 클래스 상속 구조와 이들을 구현하기 위한 클래스의 상속 구조를 독립적으로 정의하고 논리적 관점의 클래스에서 구현 클래스를 참조하는 형태로 설계된 패턴.

 

[ Birdge 패턴을 써야할 상황 예.]

검색엔진을 만드는 회사가 있다고 하자. 이 회사에서 만드는 검색 엔진은 윈도우즈,리눅스상에서도 실행되어야한다. 그러나 이 검색 엔진을 이용해서 검색 서비스를 개발하는 사람들에게는 플랫폼에 관계없이 동일한 인터페이스를 제공하려한다. 왜냐하면 이 회사의 검색엔진을 사용하는 고객들은 운영체제환경이 바뀐다고 해서 자신이 개발한 프로그램을 일일이 수정하기 원하지 않기 때문이다. 그렇다면 어떤 형태로 검색 엔진에 대한 클래스 라이브러리를 제공하는 것이 이러한 요구 사항을 만족 시키겠는가?

 

[ Birdge 패턴 샘플 소스코드.]

   
#include <string>
#include <iostream>
using namespace std;

class BTree { };

class SearchEngineImp
{
public:
	virtual bool Search(string s, string idxFn) = 0;
	virtual bool Search(string s, BTree& bTree) = 0;
};

class UnixSearchEngineImp : public SearchEngineImp
{
public:
	bool Search(string s, string idxFn)
	{
		// -- Unix 환경에 맞추어 idxFn 에서 문자열 검색
		return true;
	}
	bool Search(string s, BTree& bTree)
	{
		// -- Unix 환경에 맞추어 BTree 에서 문자열 검색
		return true;
	}
};

class WindowsSearchEngineImp : public SearchEngineImp
{
public:
	bool Search(string s, string idxFn)
	{
		// -- MS Windows 환경에 맞추어 idxFn 에서 문자열 검색
		return true;
	}
	bool Search(string s, BTree& bTree)
	{
		// -- MS Windows 환경에 맞추어 BTree 에서 문자열 검색
		return true;
	}
};

class SearchEngine
{
public:
	SearchEngine() { pImp_ = 0; }
	virtual bool Search(string s) = 0;

protected:
	SearchEngineImp * GetSearchEngineImp()
	{
		if (pImp_ == 0)
		{
#ifdef  __WIN32__
			pImp_ = new WindowsSearchEngineImp;
#else
			pImp_ = new UnixSearchEngineImp;
#endif
		}
		return pImp_;
	}

private:
	SearchEngineImp * pImp_;
};

class WebSearchEngine : public SearchEngine
{
private:
	string indexFn_;

public:
	WebSearchEngine(string idxFn) { indexFn_ = idxFn; }
	bool Search(string s)
	{
		return GetSearchEngineImp()->Search(s, indexFn_);
	}
};

class DBSearchEngine : public SearchEngine
{
private:
	BTree bTree_;

public:
	bool Search(string s)
	{
		return GetSearchEngineImp()->Search(s, bTree_);
	}
};

int main()
{
	WebSearchEngine finder("inverted_file4web.idx");
	finder.Search("디자인 패턴");
}

 

 

 외부프로그램들은 모두 SearchEngine 및 그 하위클래스들을 참조할 것이기 때문에 구현 플랫폼에

무관하게 코딩이 가능하다. 반면 실직적인 구현은 SearchEngineImp 및 그 하위 클래스들에 의해

이루어진다. 새로운 구현 플랫폼이 필요할 경우 SearchEngineImp의 하위클래스로 추가 정의만

하면 되기 때문에 편리하다. 더불어 논리적은 클래스 상속 구조와 구현 플랫폼에 따른 클래스 상속

구조가 독립되어 있으므로 논리적인 클래스를 추가한다 하더라도 구현 클래스를 추가로 정의할

 필요가 없는 장점도 있다.

 

[ Birdge 패턴의 일반적인 클래스 구조.]

 

 

[ Birdge 패턴의 유용한 경우]

1. 인터페이스와 구현 방식이 완전 결합 되는 것을 피하고 싶을때.

2. 인터페이스와 구형 방식이 각각 서로 다른 형태의 하위 클래스 구조를 가지면서 확정 되기를 원할때

3 .인터페이스의 구현 방식이 변경되더라도 그 인터페이스를 사용하는 Client 소스코드는 다시 컴파일하

   지 않아야할 때

4. 인터페이스 구현 방식을 사용자에게 완전히 숨기고 싶을때

5. 어떤 클래스의 상속구조가 여러개 의 분류 기준에 의해 정의되어 복잡하고 새로운 하위 클래스 정의

   가 힘들어 각 분류 기준마다 독립된 클래스 상속 구조를 정의하고 싶을때

6 .하나의 구현객체를 여러개의 인터페이스 객체가 공유하게 만들면서도 사용자는 이를 알지 못하게 하

   고싶을때.

 

[ Birdge 장점]

장점

1.인터페이스와 구현을 분리 시켜줍니다.

2.실행 시간에 구현 객체를 바꾸거나 설정할 수 있게 해줍니다.

3.인터페이스와 구현이 분리됨으로써 구현 내용이 변하더라도 인터페이스 클래스와

  사용자는 다시 컴파일 할 필요가 없습니다.

4.인터페이스가 분리 됨으로써 전반적인 설계가 좀더 계층화 구조화 될수있습니다.

5.사용자 입장에서는 인터페이스와 어떤 객체로 구현이 이루어지는지만 알고 구체적인 구현내용은 알 필

  요가 없어서 좋다.

6.인터페이스 클래스와 구현 클래스가 별도의 상속 구조를 가지므로 서로 독립적으로 확장이 가능하다.

7.구현의 자세한 부분 예들 들어 같은 객체를 공유한다든지, Reference Counting 기법을 사용한다든지

    하는 것들은 사용자에게 숨길수있다.

 

끝으로 브릿지패턴과 어뎁터 패턴을 비교해보면 어뎁터패턴은 서로 관계가 없었던 클래스들을 어느 순간 필요에 의해 서로 엮어주기 위해 사용하는 것인 반면,브릿지 패턴은 애초에 인터페이스와 구현을 서로 독립적으로 나누어 설계하기 위해 사용한다는 것이 가장 큰 차이점이다.