Factory Pattern là gì ?
Factory Pattern là 1 Creational Design Pattern.
Định nghĩa 1 interface hoặc abstract class để tạo đối tượng nhưng để cho các lớp con quyết định việc tạo ra các instance của lớp.
Lớp cha chỉ định tất cả các phương thức và uỷ quyền các khởi tạo chi tiết cho các lớp con được cấp bởi client.
Factory Method giúp thiết kế tuỳ biến hơn.
Tương tự Abstract Factory nhưng không nhấn mạnh vào family.
Đặt vấn đề
Khi lập trình 1 game có nhiều loại Monster, có lớp Monster
trừu tượng và các loại Monster kế thừa từ nó:
// class abstract Monster class Monster { public: Monster() {}; ~Monster() {}; virtual void Appear() = 0; }; // class monster Lion class Lion : public Monster { public: Lion() {}; ~Lion() {}; virtual void Appear() { cout << "A Lion has appeared!" << endl; } }; //class monster Dragon class Dragon : public Monster { public: Dragon() {}; ~Dragon() {}; virtual void Appear() { cout << "A Dragon has appeared!" << endl; } }; // class monster Giant class Giant : public Monster { public: Giant() {}; ~Giant() {}; virtual void Appear() { cout << "A Giant has appeared!" << endl; } };
Khởi tạo 1 đối tượng, sử dụng toán tử new:
Monster *m_Lion1 = new Lion(); Monster *m_Dragon1 = new Dragon(); Monster *m_Giant1 = new Giant();
Cần 1 đối tượng có thể quản lý việc khởi tạo các đối tượng này, chỉ cần truyền vào yêu cầu, thì đối tượng đó sẽ trả về đối tượng tương ứng.
Sử dụng Factory Pattern
Factory là nhà máy sẽ "sản xuất" các đối tượng theo yêu cầu.
Khai báo 1 enum tập hợp các yêu cầu:
enum eMonster { LION, DRAGON, GIANT, MONSTER_COUNT };
class MonsterFactory { public: MonsterFactory() {}; ~MonsterFactory() {}; static Monster *createMonster(eMonster _MonsterID) { switch (_MonsterID) { case LION: { return new Lion(); break; } case DRAGON: { return new Dragon(); break; } case GIANT: { return new Giant(); break; } default: { return NULL; break; } } } };
Sử dụng Factory:
int main() { Monster *m_Lion1 = MonsterFactory::createMonster(eMonster::LION); Monster *m_Dragon1 = MonsterFactory::createMonster(eMonster::DRAGON); Monster *m_Giant1 = MonsterFactory::createMonster(eMonster::GIANT); m_Lion1->Appear(); m_Dragon1->Appear(); m_Giant1->Appear(); return 0; }
Output:
A Lion has appeared!
A Dragon has appeared!
A Giant has appeared!
Khi có tạo 1 class Monster
mới, thêm nó vào trong Factory để quản lý việc khởi tạo dễ dàng hơn.
Ứng dụng của Factory Pattern
Khởi tạo 1 đối tượng ngẫu nhiên và dùng vòng lặp sinh ra 1 mảng các đối tượng.
Khởi tạo đối tượng ngẫu nhiên
Sử dụng hàm Random
int main() { srand(time(NULL)); eMonster RandomMonsterID = eMonster(rand() % eMonster::MONSTER_COUNT); Monster *RandomMonster = MonsterFactory::createMonster(RandomMonsterID); RandomMonster->Appear(); return 0; }
Output:
A Dragon has appeared!
Mỗi lần chạy sẽ ra kết quả khác nhau, hoàn toàn ngẫu nhiên.
Sử dụng vòng lặp sinh ra một mảng các đối tượng
int main() { Monster *m_MonsterArray[eMonster::MONSTER_COUNT]; for (int i = 0; i < eMonster::MONSTER_COUNT; i++) { m_MonsterArray[i] = MonsterFactory::createMonster(eMonster(i)); } return 0; }