본문 바로가기

기타/Design pattern

Abstract Factory pattern


1. 제품군별 객체 생성

1.1. 제품군(Product Family)이란?

- 같은 환경이나 조건에서 실행될 클래스만을 모아 놓은 것

1.2. 문제점

- 시스템의 환경에 따라 클래스 객체를 생성

1.3 해결책

①기본적 방법(조건 비교 방식)

- 조건에 따라 생성

- 비교문장이 존재하므로 샐운 조건 추가시 프로그램 전체를 수정

EX)

void ScanParse()

{

if(strncasecmp(sysInfo.sysname, HPUX, strlen(HPUX)) == 0) {

//HP용객체생성및사용

HPScanner scanner;

HPParser parse;

}

 

else if(strncasecmp(sysInfo.sysname, SUNOS, strlen(SUNOS)) == 0) {

//Sun용객체생성및사용

SunScanner scanner;

SunParser parse;

}

 

else {

//지원하지않는시스템환경

cout << sysInfo.sysname << "does not supported" << endl;

}

}

int main()

{

//OS버전및하드웨어타입정보얻기위한시스템함수

if(uname(&sysInfo) < 0) {

cout << "Error Occurred" << endl;

return (-1);

}

ScanParse();

}

②객체 생성 전담 클래스 활용 방식

- 변경될 가능성이 많은 프로그램 부분을 한 곳으로 모아서 작업 수행 => 클래스화

- 클래스 내부에 숨겨서 필요한 경우 필요한 내부만변경(정보 은닉) => 변경 범위의 최소화

- 소스코드 내에는 비교문장이 여전히 존재

- 새로운 조건 추가시 이전 소스코드를 면밀히 분석해서 수정 => 이전 소스와의 독립성이 떨어짐

 

③Abstract Factory패턴 (상속을 이용)

1) 상위 클래스가 여러 하위 클래스의 공통된 데이터를 추출해서 관리

2) 상위 클래스는 전반적이니 자료형. 외부에 공통적 인터페이스 제공

하위 클래스는 각기 다른 구현 내용(다형성에 따라 결정)

※다형성 - 한 타입의 참조 변수로 여러 타입의 객체를 참조

 

class CompilerFactory {

public:

virtual Scanner* CreateScanner() = 0;

virtual Parser* CreateParser() = 0;

virtual CodeGenerator* CreateCodeGenerator() = 0;

virtual Optimizer* CreateOptimizer() = 0;

};

 

class HPCompilerFactory : public CompilerFactory{

public :

Scanner* CreateScanner() { new HPScanner; }

Parser* CreateParser() { new HPParser; }

CodeGenerator* CreateCodeGenerator() { new HPCodeGenerator; }

Optimizer* CreateOptimizer() { new HPOptimizer; }

};

 

class SunCompilerFactory : public CompilerFactory{

public :

Scanner* CreateScanner() { new SunScanner; }

Parser* CreateParser() { new SunParser; }

CodeGenerator* CreateCodeGenerator() { new SunCodeGenerator; }

Optimizer* CreateOptimizer() { new SunOptimizer; }

};

int main()

{

 

struct utsname sysInfo;

 

//OS버전및하드웨어타입정보얻기위한시스템함수

if(uname(&sysInfo) < 0) {

cout << "Error Occurred" << endl;

return (-1);

}

 

if(strncasecmp(sysInfo.sysname, HPUX, strlen(HPUX)) == 0) {

//HP용객체생성및사용

pFactory = new HPCompilerFactory;

}

 

else if(strncasecmp(sysInfo.sysname, SUNOS, strlen(SUNOS)) == 0) {

//Sun용객체생성및사용

pFactory = newSunCompilerFactory;

}

 

else {

//지원하지않는시스템환경

cout << sysInfo.sysname << endl;

return (0);

}

}

 

2. Abstract Factory 패턴

- 제품군을 구성하는 클래스의 객체를 전담 클래스를 두고 새로운 제품군 생성을 추가하는 것이 쉽도록 클래스 상속 도입(이전 소스와의 독립성)

구체적인 제품군별 Factory클래스 상위에 Abstract Base Class를 정의 

 

 

  2.1. 장점

① 동일한 제품군에 속하는 객체를 생성하기 위해 일일이 검사할 필요가 없다.

② 기존 소스코드와는 독립적으로 새로운 제품군 추가 가능

 

2.2. 단점

①제품군의 개수가 늘어날수록 Concrete Factory클래스 개수가 늘어난다.

②제품군의 새로운 제품 추가시 모든 Factory클래스에 추가

 

2.3. 고려사항

① Factory 객체를 하나만 생성. 유지

- 구체적인 Concrete Factory객체가 하나만 필요한 경우가 많다.

- 특정객체를 하나만 명백히 보장하고 싶을 경우 Singleton패턴 적용

 

②복제를 통해 제품 객체 생성

- 미리 생성해야 할 객체를 종류별로 Factory클래스에 등록

- 객체 생성 요청시 이를 복제해 주는 방식

- 어떤 제품군의 객체를 생성할 지는 처음 등록된 객체에 의해 결정 => Prototype 패턴

class CompilerFactory {

public:

CompilerFactory(Scanner* pScanner): pScanner_(pScanner) {}

 

Scanner* CreateScanner() { return pScanner_->Clone();

 

private:

Scanner* pScanner_;

 

};

 

③새로운 제품 종류의 추가시 문제 해결 방법

- Factory는 생성할 제품의 종류에 따라 각기 다른 멤버함수를 갖는다.

- 객체 생성을 위한 모든 멤버 함수를 하나의 멤버함수로 통일

- 멤버함수의 인자로 생성하고자 하는 객체의 원형을 직접 전달

- 객체의 복제객체를 생성하는 Prototype패턴 활용

class CompilerFactory {

public:

virtual Product* CreateProduct(int type) = 0;

};

 

class HPCompilerFactory : public CompilerFactory{

public :

Product* CreateProduct(int type) {

switch(type) {

case SCANNER : return new HPScanner;

}

}

};

 

class SunCompilerFactory : public CompilerFactory{

public :

Product* CreateProduct(int type) {

switch(type) {

case SCANNER : return new HPScanner;

}

}

};

 

 

 

 

 

 

 

'기타 > Design pattern' 카테고리의 다른 글

Singleton pattern  (0) 2009.04.27
Decorator pattern  (0) 2009.04.27
Builder pattern  (0) 2009.04.27
Adapter pattern  (0) 2009.04.27
소프트웨어 개발 기본 요소  (0) 2009.04.27