끝나지 않는 프로그래밍 일기

Factory method pattern은 객체를 생성하기 위한 인터페이스를 정의하지만, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 subclass가 내리도록 한다. 이 패턴을 이용하면 클래스의 인스턴스를 만드는 일을 subclass에게 맡길 수 있다.


구조

UML 클래스 다이어그램


  • Product: Factory method가 생성하는 객체의 인터페이스를 정의한다.
  • ConcreteProduct: Product 클래스에 정의된 인터페이스를 실제로 구현한다.
  • Creator: Product 타입의 객체를 반환하는 Factory method를 선언한다. Creator 클래스는 Factory method를 기본적으로 구현하는데, 이 구현에서는 ConcreteProduct 객체를 반환한다. 또한 Product 객체의 생성을 위해 Factory method를 호출한다.
  • ConcreteCreator: Product를 실제로 생산하는 클래스. Factory method를 재정의하여 ConcreteProduct의 인스턴스를 반환한다.

장단점

  1. Facotry method로 클래스 내부에서 객체를 생성하는 것이 객체를 직접 생성하는 것보다 훨씬 응용성이 높아진다.
  2. OCP(Open-Closed Principle). 기존의 client 코드를 수정하지 않고 새로운 유형의 제품을 프로그램에 넣을 수 있다.

예시

아래와 같이 MazeGame 클래스 내에 Factory method를 정의한다. 여기서 MakeMaze(), MakeRoom(), MakeWall(), MakeDoor() method가 Factory method다.

class MazeGame
{
public:
	Maze* CreateMaze(MazeBuilder&);

	virtual Maze* MakeMaze() const
	{ return new Maze; }

	virtual Room* MakeRoom(int n) const
	{ return new Room(n); }

	virtual Wall* MakeWall() const
	{ return new Wall; }

	virtual Door* MakeDoor(Room * r1, Room * r2) const
	{ return new Door(r1, r2); }
};

Factory method를 통해 CreateMaze를 다시 써보면 아래와 같다.

Maze* MazeGame::CreateMaze(MazeBuilder& builder) {
	Maze* aMaze = MakeMaze();

	Room* r1 = MakeRoom(1);
	Room* r2 = MakeRoom(2);
	Door* theDoor = MakeDoor(r1, r2);

	aMaze->AddRoom(r1);
	aMaze->AddRoom(r2);

	r1->SetSide(North, MakeWall());
	r1->SetSide(East, theDoor);
	r1->SetSide(South, MakeWall());
	r1->SetSide(West, MakeWall());

	r2->SetSide(North, MakeWall());
	r2->SetSide(East, MakeWall());
	r2->SetSide(South, MakeWall());
	r2->SetSide(West, theDoor);

	return aMaze;
}

다른 미로 게임을 만든다면, MazeGame 클래스를 상속해서 미로의 부분을 재정의하면 된다. 예를 들어, BombedMazeGame 클래스는 Room과 Wall 객체를 다시 정의하여 폭탄을 맞은 것들을 반환하도록 만든다.

class BombedMazeGame : public MazeGame {
public:
	BombedMazeGame();

	virtual Wall* MakeWall() const
	{
		return new BombedWall;
	}

	virtual Room* MakeRoom(int n) const
	{
		return new RoomWithBomb(n);
	}
};


'메모 > Design pattern' 카테고리의 다른 글

메모. Proxy pattern  (0) 2019.11.18
메모. Facade pattern  (0) 2019.11.17
메모. Factory method pattern  (0) 2019.05.19
메모. Builder pattern  (0) 2019.05.18
메모. Concrete class  (1) 2019.05.13
메모. Abstract factory pattern  (0) 2019.05.13