工厂模式的定义和用途

工厂模式的主要目的就是将对象创建的过程封装起来,客户端只需要创建对象,而不需要去了解创建对象的过程。

举一个例子(骷髅、士兵、弓箭手等):如果我们在客户端去创建对象的话,我们还要去根据不同的类型去判断需要创建什么对象,怎么去创建的逻辑。而使用工厂模式的话,客户端只需要直接告诉工厂,我需要创建骷髅的对象,你直接给我就行了。这样客户端就无需知道创建的过程,只需要知道通过工厂,我可以拿到这个对象。

简单/静态工厂模式

接下来,我们将以一个案例去学习简单工厂模式

假设我们要开发一个地牢游戏,需要生成不同类型的怪物:

不用工厂模式的写法

// 直接创建具体怪物对象
monster = Zombie()  // 创建僵尸
boss = Demon()      // 创建恶魔

//当需要根据条件创建不同怪物时:
monster_type = “zombile”
if(monster_type == "zombie")
    monster = new Zombie()
else if(monster_type == "skeleton")
    monster = new Skeleton()
else if(monster_type == "demon")
    monster = new Demon()
  1. 当客户端的某个部分需要用到怪物,也可能在另一个部分中,也会用到创建怪物的逻辑。就会造成创建逻辑分散在多处,难以维护

  2. 当我们创建一个新的怪物的时候,需要修改这里面的代码。

  3. 暴露的具体的类,违反了封装原则。

使用简单工厂模式

  1. 定义怪物的接口

// 怪物接口(抽象产品)
public interface IMonster 
{
    void Attack();
}
  1. 创建具体的怪物类

// 具体怪物类(具体产品)
public class Zombie : IMonster
{
    public void Attack() 
    {
        Console.WriteLine("僵尸撕咬攻击!");
    }
}

public class Skeleton : IMonster
{
    public void Attack()
    {
        Console.WriteLine("骷髅弓箭射击!");
    }
}

public class Demon : IMonster
{
    public void Attack()
    {
        Console.WriteLine("恶魔火焰喷射!");
    }
}
  1. 创建怪物的工厂

public class MonsterFactory
{
    // 创建怪物的静态方法
    public static IMonster CreateMonster(string monsterType)
    {
        switch (monsterType.ToLower())
        {
            case "zombie":
                return new Zombie();
            case "skeleton":
                return new Skeleton();
            case "demon":
                return new Demon();
            default:
                throw new ArgumentException("未知的怪物类型");
        }
    }
}
  1. 客户端使用

class Program
{
    static void Main(string[] args)
    {
        // 通过工厂创建怪物
        IMonster monster1 = MonsterFactory.CreateMonster("zombie");
        IMonster monster2 = MonsterFactory.CreateMonster("skeleton");
        IMonster boss = MonsterFactory.CreateMonster("demon");

        monster1.Attack(); // 输出:僵尸撕咬攻击!
        monster2.Attack(); // 输出:骷髅弓箭射击!
        boss.Attack();     // 输出:恶魔火焰喷射!
    }
}
  1. 动态生成挂物军团

void GenerateMonsterArmy(int count)
{
    string[] types = { "zombie", "skeleton", "demon" };
    Random rand = new Random();
    
    for (int i = 0; i < count; i++)
    {
        string type = types[rand.Next(types.Length)];
        IMonster monster = MonsterFactory.CreateMonster(type);
        monster.Attack();
    }
}

// 生成5个随机怪物
GenerateMonsterArmy(5); 

抽象工厂模式

现在我们可以通过简单工厂模式创建不同的对象了。但是如果我们想要创建一个组合,比如:远程怪物有弓箭手、炮兵等。近战怪物有士兵、骷髅兵等。我们想创建一个组合了。

接下来我们有一个例子

1. 定义抽象产品接口

// 汉堡抽象类
public interface IHamburger {
    void Describe();
}

// 薯条抽象类
public interface IFries {
    void ShowCutStyle();
}

// 饮料抽象类
public interface IDrink {
    void DisplayFlavor();
}

2. 创建具体产品类

// 美式风味组合

class AmericanBeefBurger : IHamburger {
    public void Describe() => Console.WriteLine("美式厚牛肉汉堡");
}

class ThickCutFries : IFries {
    public void ShowCutStyle() => Console.WriteLine("粗切波浪薯条");
}

class ColaDrink : IDrink {
    public void DisplayFlavor() => Console.WriteLine("经典可乐");
}


// 日式风味组合
class JapaneseChickenBurger : IHamburger {
    public void Describe() => Console.WriteLine("日式照烧鸡腿汉堡");
}

class ThinCutFries : IFries {
    public void ShowCutStyle() => Console.WriteLine("细切直条薯条");
}

class GreenTeaDrink : IDrink {
    public void DisplayFlavor() => Console.WriteLine("煎茶风味饮料");
}

3. 定义抽象工厂接口

public interface IFastFoodFactory {
    IHamburger CreateHamburger();
    IFries CreateFries();
    IDrink CreateDrink();
}

4. 实现具体工厂类

class AmericanFoodFactory : IFastFoodFactory {
    public IHamburger CreateHamburger() => new AmericanBeefBurger();
    public IFries CreateFries() => new ThickCutFries();
    public IDrink CreateDrink() => new ColaDrink();
}

class JapaneseFoodFactory : IFastFoodFactory {
    public IHamburger CreateHamburger() => new JapaneseChickenBurger();
    public IFries CreateFries() => new ThinCutFries();
    public IDrink CreateDrink() => new GreenTeaDrink();
}

5. 客户端使用

class RestaurantSimulator {
    // 通过抽象工厂接口操作
    private IFastFoodFactory _factory;

    public RestaurantSimulator(IFastFoodFactory factory) {
        _factory = factory;
    }

    public void PrepareMeal() {
        var burger = _factory.CreateHamburger();
        var fries = _factory.CreateFries();
        var drink = _factory.CreateDrink();

        burger.Describe();
        fries.ShowCutStyle();
        drink.DisplayFlavor();
    }
}

// 使用示例
var americanRestaurant = new RestaurantSimulator(new AmericanFoodFactory());
americanRestaurant.PrepareMeal();
/* 输出:
美式厚牛肉汉堡
粗切波浪薯条
经典可乐 */

var japaneseRestaurant = new RestaurantSimulator(new JapaneseFoodFactory());
japaneseRestaurant.PrepareMeal();
/* 输出:
日式照烧鸡腿汉堡
细切直条薯条
煎茶风味饮料 */

工厂工厂模式