参考文章:https://blog.csdn.net/yupu56/article/details/53669210

简单工厂 - 创建型

简单工厂模式的目的是用来创建不同类型的对象。在工厂模式中,它提供了一种创建对象的最佳方式 ,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
设计模式-工厂模式 - 图1

  1. namespace SimpleFactory
  2. {
  3. #region 产品
  4. public interface IPhone
  5. {
  6. void Version();
  7. }
  8. //苹果手机
  9. public class PhoneApple : IPhone
  10. {
  11. public virtual void Version()
  12. {
  13. Debug.Log("苹果手机");
  14. }
  15. }
  16. //三星手机
  17. public class PhoneSamsung : IPhone
  18. {
  19. public virtual void Version()
  20. {
  21. Debug.Log("三星手机");
  22. }
  23. }
  24. #endregion
  25. #region 工厂
  26. public class SimpleFactory
  27. {
  28. public static IPhone Create(int id)
  29. {
  30. switch (id)
  31. {
  32. case 1:
  33. return new PhoneApple();
  34. case 2:
  35. return new PhoneSamsung();
  36. }
  37. return null;
  38. }
  39. }
  40. #endregion
  41. }
  1. Void Start()
  2. {
  3. PhoneApple phoneApple = (PhoneApple)SimpleFactory.Create(1);
  4. phoneApple.Version();//输出苹果手机的方法
  5. }

简单工厂模式的Create()方法里,可以添加各种逻辑,用于创建对应的实例。unity3d中很多时候创建的是游戏中的物件,这时简单工厂模式中创建者的参数可以对应prefab的名字。

优点:

  • 实现逻辑清晰,根据不同的创建参数创建对应实例,一个调用者想创建一个对象,只要知道其下标或者名称就可以了。
  • 屏蔽产品的具体实现,调用者只关心产品的接口。
  • 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。

    缺点:

    每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
    再思考一下
    假如我们不希望通过判断参数是1还是2,来进行不同实例的生成呢? 显然,一旦我们需要新的逻辑来产生实例的话,我们就不得不对代码进行修改。
    我们可以发现简单工厂模式的一些问题: Open-closed原则,即是对扩展开放,对修改封闭。使用简单工厂模式时,很多时候违背了这一原则。同时,由于产生不同实例的方法在可预见的将来有可能会变得很复杂,是否满足单一职责这一点也值得商榷。
    那么,我们有办法解决这个问题吗?嗯,接下来就是抽象程度更高的方法出场了。

    工厂方法

    工厂方法与简单工厂最大的区别,在于工厂方法将工厂进行了抽象,将实现逻辑延迟到工厂的子类。
    设计模式-工厂模式 - 图2

    1. namespace Factory
    2. {
    3. #region 产品
    4. public interface IPhone
    5. {
    6. void Version();
    7. }
    8. //苹果手机
    9. public class ProductApple : IPhone
    10. {
    11. public virtual void Version()
    12. {
    13. Debug.Log("苹果手机");
    14. }
    15. }
    16. //三星手机
    17. public class ProductSamsung : IPhone
    18. {
    19. public virtual void Version()
    20. {
    21. Debug.Log("三星手机");
    22. }
    23. }
    24. #endregion
    25. #region 工厂
    26. public interface IFactory
    27. {
    28. IPhone Create();
    29. }
    30. public class AppleFactory : IFactory
    31. {
    32. public virtual IPhone Create()
    33. {
    34. return new ProductApple();
    35. }
    36. }
    37. public class SumsungFactory : IFactory
    38. {
    39. public virtual IPhone Create()
    40. {
    41. return new ProductSamsung();
    42. }
    43. }
    44. #endregion
    45. }
    1. void Start()
    2. {
    3. AppleFactory phoneApple = new AppleFactory();
    4. phoneApple.Create().Version();
    5. }

    优点:

    工厂方法比简单工厂多了一层抽象。
    由于抽象工厂层的存在,当我们需要修改一个实现的时候,我们不需要修改工厂的角色,只需要修改实现的子类就可以完成这个工作。
    同样,当我们需要增加一个新产品的时候,我们也不需要修改工厂的角色,只需要增加一个新的实现工厂来完成实现就可以了。
    显然,这样更易于扩展,并且,整体代码的层级结构更加分明,创建实际产品的职责更加单一。
    此外,很显然客户在定义工厂角色的时候不需要知道实现子类。只有当实际需要创建的时候,才动态指定子类。这同样带来了代码的稳定性和最小可知性。

    缺陷:

    显然,使用工厂方法的代码量是多于简单工厂的。
    同时,每增加一个新的产品,就会增加一个新的工厂类,代码的复杂程度自然也随之上升了。我们会为此创建很多的工厂。

    Unity相关应用

    在工厂模式中,我们关注的是一个产品整体,无需关心产品各个部分是如何生产出来的,工厂方法模式的产品一般是单一性质产品,例如各个不同品牌的汽车,他们都是汽车模样。
    需要管理某一类别不同种类的的对象,例如 掉落的物品 - 金币/道具/装备/材料;技能树 - 回复类/伤害类/召唤类;不同的道具(道具抽象)- 药品/武器/防具; Unity中创建不同类型的UI(Button、Text、Toggle)等等。
    ScriptableObject创建子弹:https://blog.csdn.net/weixin_44806268/article/details/120630090
    单例+对象池+子弹工厂:https://blog.csdn.net/qq_52855744/article/details/122285783