설명
생성용 인터페이스 Factory 와, 객체용 인터페이스 Factory.
인터페이스를 공유하는 객체들이 모두 Factory 인터페이스로 생성되므로
객체를 생성하거나 수정하는데 일관성을 유지할 수 있음.
문제는 일부만 바꿔도 서브클래스들을 통채로 다 바꿔야하는 경우가 생김.
예제 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class MazeFactory { public: MazeFactory() = default; virtual Maze* MakeMaze() const { return new Maze; } virtual Wall* MakeWall() const { return new Wall; } virtual Room* MakeRoom(int n) const { return new Room(n); } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new Door(r1, r2); } }; class EnchantedMazeFactory : public MazeFactory { public: EnchantedMazeFactory() = default; virtual Room* MakeRoom(int n) const { return new EnchantedRoom(n, CastSpell()); } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new DoorNeedingSpell(r1, r2); } protected: Spell* CastSpell() const { return new Spell("spell"); }; }; | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | Maze* MazeGame::CreateMaze() { Maze* maze = m_factory->MakeMaze(); Room* r1 = m_factory->MakeRoom(1); Room* r2 = m_factory->MakeRoom(2); Door* theDoor = m_factory->MakeDoor(r1, r2); maze->AddRoom(r2); maze->AddRoom(r1); r1->SetSide(North, m_factory->MakeWall()); r1->SetSide(East, theDoor); r1->SetSide(South, m_factory->MakeWall()); r1->SetSide(West, m_factory->MakeWall()); r2->SetSide(North, m_factory->MakeWall()); r2->SetSide(East, m_factory->MakeWall()); r2->SetSide(South, m_factory->MakeWall()); r2->SetSide(West, theDoor); m_mazes.push_back(maze); return maze; } | cs |
Maze 가 Wall, Room, Door 로 구성되어 있다고 하면,
Maze 를 만들고 안에 Wall, Room, Door 를 추가하기 위해
MazeFactory 를 통해서만 가능하게 구현하는 것.
약간 다른 버전인 Maze 를 상속받은 EnchantedMaze 를 만들기 위해
MazeFactory 를 상속받은 EnchantedMazeFactory 를 호출해야함.
인터페이스는 Maze 와 상속 시리즈들이 서로 같듯이
MazeFactory 도 ConcreteFactory 에 해당되는 시리즈들이 같은 인터페이스를 가짐.
그래서 객체 사이의 일관성을 높혀줌.
추가 설명
Factory 자체는 대개 Factory Method 로 구현되고
Prototype 과는 경쟁적이지만 같이 사용되기도 함.
또한 Factory 는 하나만 있으면 되서 Singleton 으로도 구현되기도 함.
댓글 없음:
댓글 쓰기