Search…

Design Pattern: Factory Pattern

26/09/20203 min read
Tổng quan và hướng dẫn hiện thực Factory Pattern với C++.

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;
}
IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024