工厂模式(Factory Pattern) C++

上一节:单例模式(Singleton Pattern) C++

文章目录

  • 0.理论
  • 1.实践
    • 1.1 简单工厂模式(Simple Factory Pattern)
    • 1.2 工厂方法模式(Factory Method Pattern)
    • 1.3 抽象工厂模式(Abstract Factory Pattern)

0.理论

工厂模式(Factory Pattern) 是一种创建型设计模式,它提供了一种创建对象的接口,但具体的对象创建逻辑被延迟到子类或工厂类中进行实现。这样可以将对象的创建和使用分离,使得系统更加灵活和可扩展。

在工厂模式中,通常会定义一个抽象工厂接口或抽象类,该接口或抽象类声明了一个创建对象的方法,但不具体实现。然后通过具体的工厂类实现这个接口或抽象类,负责创建具体的对象。
工厂模式的核心思想是通过工厂类来封装对象的创建过程,客户端只需要通过工厂类来获取所需的对象,而不需要直接调用对象的构造函数。这样做的好处是,客户端可以通过统一的接口来创建对象,而无需关心具体的创建细节,从而实现了解耦和松耦合。

工厂模式可以分为以下几种类型:

  • 简单工厂模式(Simple Factory Pattern):由一个工厂类根据传入的参数决定创建哪种产品类的对象。简单工厂模式的核心是一个工厂类,它负责根据外部条件返回合适的对象实例。
  • 工厂方法模式(Factory Method Pattern):定义一个创建对象的接口,但将具体的对象创建延迟到子类中进行实现。每个子类可以通过实现工厂方法来创建属于自己的对象。
  • 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式可以看作是多个工厂方法模式的组合,它的核心是一个抽象工厂接口,定义了一系列可以创建不同类型对象的方法。

工厂模式的优点包括:

  • 将对象的创建和使用分离,客户端无需关心具体的对象创建过程,只需通过工厂类获取所需的对象。
  • 提供了一种可扩展的方式,当需要新增一种产品时,只需添加相应的具体产品类和对应的工厂类即可,不需要修改现有代码。
  • 提高了代码的可维护性和灵活性,符合面向对象设计原则中的开闭原则。

总之,工厂模式是一种常用的设计模式,可以帮助我们有效地组织和管理对象的创建过程,提高系统的可扩展性和灵活性。

1.实践

1.1 简单工厂模式(Simple Factory Pattern)

假设我们正在开发一个游戏,其中有多个角色可以选择,比如战士(Warrior)、法师(Mage)和射手(Archer)。每个角色都有不同的属性和技能。

首先,我们需要定义一个抽象基类(或接口)作为角色的通用定义:

// 角色基类
class Character {
public:
    virtual void Attack() = 0;
    virtual void Defense() = 0;
    // 其他共有方法和属性
};

接下来,我们创建具体的角色类,实现抽象基类中的方法:

// 战士类
class Warrior : public Character {
public:
    void Attack() override {
        cout << "战士发起了一次攻击!" << endl;
        // 具体的攻击逻辑
    }

    void Defense() override {
        cout << "战士进行了一次防御!" << endl;
        // 具体的防御逻辑
    }
};

// 法师类
class Mage : public Character {
public:
    void Attack() override {
        cout << "法师施放了一次法术攻击!" << endl;
        // 具体的攻击逻辑
    }

    void Defense() override {
        cout << "法师施放了一次防御技能!" << endl;
        // 具体的防御逻辑
    }
};

// 射手类
class Archer : public Character {
public:
    void Attack() override {
        cout << "射手放出了一支箭!" << endl;
        // 具体的攻击逻辑
    }

    void Defense() override {
        cout << "射手使用了闪避技能!" << endl;
        // 具体的防御逻辑
    }
};

接下来,我们定义一个简单工厂类,负责根据输入的角色类型创建对应的角色对象:

// 角色工厂类
class CharacterFactory {
public:
    static Character* CreateCharacter(string characterType) {
        if (characterType == "Warrior")
            return new Warrior();
        else if (characterType == "Mage")
            return new Mage();
        else if (characterType == "Archer")
            return new Archer();
        else
            return nullptr;
    }
};

最后,我们可以在游戏中使用简单工厂模式来创建具体的角色对象:

int main() {
    Character* warrior = CharacterFactory::CreateCharacter("Warrior");
    warrior->Attack();
    warrior->Defense();

    Character* mage = CharacterFactory::CreateCharacter("Mage");
    mage->Attack();
    mage->Defense();

    Character* archer = CharacterFactory::CreateCharacter("Archer");
    archer->Attack();
    archer->Defense();

    delete warrior;
    delete mage;
    delete archer;

    return 0;
}

输出结果可能如下所示:

战士发起了一次攻击!
战士进行了一次防御!
法师施放了一次法术攻击!
法师施放了一次防御技能!
射手放出了一支箭!
射手使用了闪避技能!

通过角色工厂类的CreateCharacter方法来创建不同类型的角色对象,而不需要直接调用具体角色类的构造函数。这样,客户端只需提供角色类型,而不需要关心具体的创建过程,实现了角色对象的创建与使用的解耦。

当然一个游戏得有关卡吧,下面使用 工厂方法模式(Factory Method Pattern)来创建关卡

1.2 工厂方法模式(Factory Method Pattern)

假设我们正在开发一个游戏,其中有多个关卡(Level)需要玩家进行挑战,每个关卡都有不同的怪物(Monster)。
首先,我们定义一个抽象基类(或接口)作为怪物的通用定义:

// 怪物基类
class Monster {
public:
    virtual void Attack() = 0;
    virtual void Defend() = 0;
    // 其他共有方法和属性
};

然后,我们创建具体的怪物类,实现抽象基类中的方法:

// 僵尸类
class Zombie : public Monster {
public:
    void Attack() override {
        cout << "僵尸发起了一次攻击!" << endl;
        // 具体的攻击逻辑
    }

    void Defend() override {
        cout << "僵尸进行了一次防御!" << endl;
        // 具体的防御逻辑
    }
};

// 骷髅类
class Skeleton : public Monster {
public:
    void Attack() override {
        cout << "骷髅发起了一次攻击!" << endl;
        // 具体的攻击逻辑
    }

    void Defend() override {
        cout << "骷髅进行了一次防御!" << endl;
        // 具体的防御逻辑
    }
};

接下来,我们定义一个抽象的关卡基类(或接口),其中包含一个工厂方法用于创建怪物对象:

// 关卡基类
class Level {
public:
    virtual Monster* CreateMonster() = 0;
    // 其他共有方法和属性
};

然后,我们创建具体的关卡类,继承关卡基类,并实现工厂方法来创建对应的怪物对象:

// 第一关卡
class Level1 : public Level {
public:
    Monster* CreateMonster() override {
        return new Zombie();
    }
};

// 第二关卡
class Level2 : public Level {
public:
    Monster* CreateMonster() override {
        return new Skeleton();
    }
};

最后,我们可以在游戏中使用工厂方法模式来创建具体的怪物对象:

int main() {
    Level* level1 = new Level1();
    Monster* monster1 = level1->CreateMonster();
    monster1->Attack();
    monster1->Defend();

    Level* level2 = new Level2();
    Monster* monster2 = level2->CreateMonster();
    monster2->Attack();
    monster2->Defend();

    delete level1;
    delete monster1;
    delete level2;
    delete monster2;

    return 0;
}

需调用关卡类的工厂方法,而不需要关心具体怪物对象的创建过程,实现了关卡对象和怪物对象的解耦。

输出结果可能如下所示:

僵尸发起了一次攻击!
僵尸进行了一次防御!
骷髅发起了一次攻击!
骷髅进行了一次防御!

以上示例展示了在游戏开发中使用工厂方法模式创建不同关卡的怪物对象。通过工厂方法模式,我们可以方便地新增其他关卡和对应的怪物类型,只需创建对应的关卡类并实现工厂方法,而不需要修改现有的怪物类和客户端代码,从而实现了代码的可扩展性和灵活性。
当然,如果你的游戏里有种族分类,每个种族里的建筑以及生活风格和习惯肯定是不一样的。下面就使用工厂方法模式(Factory Method Pattern)来实现不同的种族。

1.3 抽象工厂模式(Abstract Factory Pattern)

假设我们正在开发一个游戏,其中有不同的种族(Race),每个种族都有不同类型的兵种(Unit)和建筑(Building)。

首先,我们定义抽象基类(或接口)用于表示兵种和建筑:

// 兵种基类
class Unit {
public:
    virtual void Attack() = 0;
    virtual void Move() = 0;
    // 其他共有方法和属性
};

// 建筑基类
class Building {
public:
    virtual void ProduceUnit() = 0;
    virtual void Upgrade() = 0;
    // 其他共有方法和属性
};

接下来,我们创建具体的兵种和建筑类,实现抽象基类中的方法:

// 人族兵种类
class HumanUnit : public Unit {
public:
    void Attack() override {
        cout << "人族兵种发起了一次攻击!" << endl;
        // 具体的攻击逻辑
    }

    void Move() override {
        cout << "人族兵种进行了一次移动!" << endl;
        // 具体的移动逻辑
    }
};

// 人族建筑类
class HumanBuilding : public Building {
public:
    void ProduceUnit() override {
        cout << "人族建筑开始生产兵种!" << endl;
        // 具体的生产兵种逻辑
    }

    void Upgrade() override {
        cout << "人族建筑进行了一次升级!" << endl;
        // 具体的升级逻辑
    }
};

// 兽族兵种类
class OrcUnit : public Unit {
public:
    void Attack() override {
        cout << "兽族兵种发起了一次攻击!" << endl;
        // 具体的攻击逻辑
    }

    void Move() override {
        cout << "兽族兵种进行了一次移动!" << endl;
        // 具体的移动逻辑
    }
};

// 兽族建筑类
class OrcBuilding : public Building {
public:
    void ProduceUnit() override {
        cout << "兽族建筑开始生产兵种!" << endl;
        // 具体的生产兵种逻辑
    }

    void Upgrade() override {
        cout << "兽族建筑进行了一次升级!" << endl;
        // 具体的升级逻辑
    }
};

接下来,我们定义一个抽象工厂基类(或接口),用于创建兵种和建筑:

// 抽象工厂基类
class AbstractFactory {
public:
    virtual Unit* CreateUnit() = 0;
    virtual Building* CreateBuilding() = 0;
};

然后,我们创建具体的工厂类,继承抽象工厂基类,并实现创建兵种和建筑的方法:

// 人族工厂
class HumanFactory : public AbstractFactory {
public:
    Unit* CreateUnit() override {
        return new HumanUnit();
    }

    Building* CreateBuilding() override {
        return new HumanBuilding();
    }
};
// 兽族工厂类
class OrcFactory : public AbstractFactory {
public:
    Unit* CreateUnit() override {
        return new OrcUnit();
    }

    Building* CreateBuilding() override {
        return new OrcBuilding();
    }
};

最后,我们可以在游戏中使用抽象工厂模式来创建具体的兵种和建筑对象:

int main() {
    AbstractFactory* humanFactory = new HumanFactory();
    Unit* humanUnit = humanFactory->CreateUnit();
    Building* humanBuilding = humanFactory->CreateBuilding();

    humanUnit->Attack();
    humanUnit->Move();

    humanBuilding->ProduceUnit();
    humanBuilding->Upgrade();

    delete humanUnit;
    delete humanBuilding;
    delete humanFactory;

    AbstractFactory* orcFactory = new OrcFactory();
    Unit* orcUnit = orcFactory->CreateUnit();
    Building* orcBuilding = orcFactory->CreateBuilding();

    orcUnit->Attack();
    orcUnit->Move();

    orcBuilding->ProduceUnit();
    orcBuilding->Upgrade();

    delete orcUnit;
    delete orcBuilding;
    delete orcFactory;

    return 0;
}
    

通过使用抽象工厂模式,我们可以通过具体的工厂类来创建属于特定种族的兵种和建筑对象,而不需要直接调用具体类的构造函数。客户端只需要使用抽象工厂对象,而不需要关心具体对象的创建过程,从而实现了客户端代码与具体类的解耦。

输出结果可能如下所示:

人族兵种发起了一次攻击!
人族兵种进行了一次移动!
人族建筑开始生产兵种!
人族建筑进行了一次升级!
兽族兵种发起了一次攻击!
兽族兵种进行了一次移动!
兽族建筑开始生产兵种!
兽族建筑进行了一次升级!

以上示例展示了在游戏开发中使用抽象工厂模式创建不同种族的兵种和建筑对象。通过抽象工厂模式,我们可以方便地新增其他种族和对应的兵种、建筑类型,只需创建对应的工厂类并实现工厂方法,而不需要修改现有的兵种、建筑类和客户端代码,从而实现了代码的可扩展性和灵活性。

下一节:模板方法模式(Template Method Pattern) C++

你可能感兴趣的:(设计模式,c++,工厂模式,设计模式)