728x90

우리가 윈도우 바탕화면에서 파일들을 실행하면 각 파일의 확장자나 정보에 따라 각기 다른 프로그램이 실행이 됩니다. 이런 상황에서 생성돼야 할 객체는 그 파일에 대한 응용 프로그램과 그 파일에 대한 객체입니다. 응용 프로그램은 운영체제 혹은 explorer.exe 에서 생성이 돼야 하고 그 파일은 생성된 응용 프로그램에서 생성이 되어야 합니다.

 

간단히 구조를 보면 Application을 상속받는 각 Hwp, Ppt Application 객체를 통해 새로운 객체를 만드는 구조가 됩니다.

class Application {
    virtual void NewDocument(char* pFileName) = 0;
};

class HwpApplication : public Application {
    void NewDocument(char* pFileName) {
    	HwpDocument* hwp = new HwpDocument();
        hwp->open(pFileName);
    }
};

class PowerpointApplication : public Application {
    void NewDocument(char* pFileName) {
    	PptDocuemnt* ppt = new PptDocument();
        ppt->open(pFileName);
    }
};

위 코드는 얼핏보면 괜찮아 보일 수 있지만 NewDocument에서는 파일 종류에 따라 다른 객체를 생성해주는 부분만 다르게 됩니다. 현재는 2개의 종류만 있지만 종류가 더 늘어날수록 이런 부분은 비효율적이게 됩니다. 

 

이런 비효율적인 부분을 방지하기 위해서는 NewDocument가 구현되는 부분을 상위 클래스에서 해주면 됩니다. 이렇게 되면 각 하위 종류별 Application 클래스에서 각각 구현하던 부분과 수정의 용이성까지 챙겨갈 수 있습니다. 이를 위해서는 두 가지 방법이 있는데 첫 번째로는 Application에서 기존 NewDocument에서 파일 별 객체를 생성할 수 있는 createDocument 함수를 따로 만들어 호출해 사용하는 것입니다. createDocument 함수는 각 Application 클래스마다 다른 객체를 생성해야 하고 생성된 객체는 공통된 cNewDocument 함수에서 사용할 수 있어야 합니다. 결국 NewDocument는 상위 클래스에서 createDocuemnt는 하위 클래스에서 overridng 해서 구현이 되어야 합니다.

 

위에서 설명한 구조를 그려보면 아래와 같은 구조가 나오게 됩니다.

class Document {};
class HwpDocument : public Document {};
class PptDocuemnt : public Document {};

class Application {
    virtual Document* createDocument() = 0;
    void NewDocument(char* pFileName) {
    	Document* pDoc = createDocument();
        pDoc->open(pFileName);
    }
};

class HwpApplication : public Application {
    Document* createDocument() { return new HwpDocuemnt; }
};

class PptApplication : public Application {
    Document* createDocument() { return new PptDocuemnt; }
};

int main()
{
    HwpApplication hwp;
    hwp.NewDocument("test.hwp");
}

이렇게 최상위 클래스를 추상 클래스로 만들면 하위 클래스에서 생성되는 객체는 명확히 구분될 수 있다는 장점이 있지만 하위 클래스에서 무조건 구현을 해줘야 한다는 단점이 있습니다. 최상위 클래스를 상속받는 하위 클래스가 많아지게 된다면 이것 또한 번거로운 점이 될 수 있습니다. 상황에 따라서 최상위 클래스에서 처리를 해주는 게 나을 수 있습니다.

class Document {};
class HwpDocument : public Document {};
class PptDocuemnt : public Document {};
class AnotherDocuemnt : public Document {};

class Application {
    virtual Document* createDocument(char* pFileName) {
    	QFileInfo fi(QString(pFileName));
		QString ext = fi.suffix();  // qt에서 file의 확장자 구하는 구문
        if ( ext == "hwp" ) { return new HwpDocument; }
        else if ( ext == "ppt" ) { return new PptDocuemnt; }
        else { return new AnotherDocument; }
    }
    void NewDocument(char* pFileName) {
    	Document* pDoc = createDocument(pFileName);
        pDoc->open();
    }
};

class HwpApplication : public Application { };
class PptApplication : public Application { };
class AnotherApplication : public Application { };

int main()
{
    HwpApplication hwp;
    hwp.NewDocument("test.hwp");
}

마지막으로 template을 이용해서도 객체를 생성해줄 수 있습니다. template에 인자로 생성될 Docuemnt를 직접 전달해주게 됩니다.

class Document {};
class HwpDocument : public Document {};
class PptDocuemnt : public Document {};

class Application {
    virtual Document* createDocument() = 0;
    void NewDocument(char* pFileName) {
    	Document* pDoc = createDocument();
        pDoc->open(pFileName);
    }
};
template<class DocType>
class TemplateApplication : public Application {
    Document* createDocument() { return new DocType; }
};

int main()
{
    TemplateApplication<HwpDocument> hwp;
    hwp.NewDocument("test.hwp");
}

지금까지 소개한 패턴이 팩토리 메소드 입니다. 정확히 팩토리 메서드는 어떤 객체를 생성하는 함수입니다. 위에서 보면 createDocument가 팩토리 메서드라고 볼 수 있습니다. 팩토리 메서드는 상황에 따라 다른 객체를 생성할 때 사용하면 좋습니다. 생성될 객체는 각각의 하위 클래스에 의해 결정되고 객체의 종류가 늘어날 때마다 하위 클래스를 확장하게 됩니다. 

728x90

'Programming > C++' 카테고리의 다른 글

C++ 싱글톤 패턴  (0) 2021.05.09
C++ 프로토 타입 패턴  (0) 2021.05.08
C++ 빌더 패턴  (0) 2021.05.02
C++ 추상 팩토리 패턴  (0) 2021.05.02
C++ 상속(Inheritance)  (0) 2020.05.08

+ Recent posts