Unity3d之设计模式(二)工厂模式

转载: http://blog.csdn.net/yupu56/article/details/53669210

 

 

Unity3d之设计模式(二)工厂模式

标签: unity3d重构模式设计模式工厂模式
 分类:
 

这个系列的文章,并不会将所有用到的设计模式全部讲一遍,事实上我个人认为,并不是所有的设计模式都适用于Unity3D。这里讲的主要还是一些常用的设计模式。 
那么,本章讲的就是常见的构建型模式当中的工厂模式。

简单工厂模式

讲工厂,首先得从简单工厂说起。 
简单工厂模式的目的是用来创建不同类型的对象。在GOF的23种模式之中,只讲了工程模式的一个实例,但是我们可以根据项目的复杂程度来进行自己的改写,简单工厂就是其中的一种写法。

结构图

实现

废话少说,直接上代码。

 

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


 

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

优点

  • 简单,可以取名叫『2分钟内可以学会的设计模式』
  • 实现逻辑清晰,根据不同的创建参数创建对应实例。

名为简单工厂方法,看起来果然是很简单,对不对?那么,本着”simple is best”的逻辑,是不是我们应该大力推广简单工厂模式呢? 
答案是「No」。简单工厂模式有其固有的缺陷,在使用时需要严格限定其范围。

缺陷

让我们首先考虑一个问题。此处使用的Create()方法,直接决定我们产生实例的逻辑。 
那么,现在问题来了。 
假如我们不希望通过判断参数是1还是2,来进行不同实例的生成呢? 
显然,一旦我们需要新的逻辑来产生实例的话,我们就不得不对代码进行修改。 
当然,从理论上,我们也可以发现简单工厂模式的一些问题。 
Open-closed原则,即是对扩展开放,对修改封闭。使用简单工厂模式时,很多时候违背了这一原则。同时,由于产生不同实例的方法在可预见的将来有可能会变得很复杂,是否满足单一职责这一点也值得商榷。 
那么,我们有办法解决这个问题吗?嗯,接下来就是抽象程度更高的方法出场了。

工厂方法

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

结构图

实现

为了让我们例子更贴近生产环境,在这里采用一个更加实际的问题。 
现在我们要生产苹果手机和三星手机 ,我们用工厂方法来生成这两款手机。
上代码 

 

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


 


优点

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

缺陷

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

抽象工厂

抽象工厂和工厂方法实际上是很像的,不过抽象工厂增加了另外一个概念,就是产品族。也就是说,一个工厂可以生产一系列的产品,这些产品的定义都在工厂当中。

结构图

实现

ok。这个模式需要产品和工厂很复杂的项目才需要。直接上代码吧,就不加注释了

 

[csharp] view plain copy
 
  1. using System;  
  2. using UnityEngine;  
  3.   
  4. namespace AbstractFactory{  
  5.  
  6.     #region  产品  
  7.     public interface IPhone  
  8.     {  
  9.         void Version();  
  10.     }  
  11.     public interface IPad  
  12.     {  
  13.         void Version();  
  14.     }  
  15.   
  16.     //苹果手机  
  17.     public class PhoneApple : IPhone  
  18.     {  
  19.         public virtual void Version()  
  20.         {  
  21.             Debug.Log("苹果手机");  
  22.         }  
  23.     }  
  24.     //三星手机  
  25.     public class PhoneSamsung : IPhone  
  26.     {  
  27.         public virtual void Version()  
  28.         {  
  29.             Debug.Log("三星手机");  
  30.         }  
  31.     }  
  32.     //苹果pad  
  33.     public class PadApple : IPad  
  34.     {  
  35.         public virtual void Version()  
  36.         {  
  37.             Debug.Log("苹果pad");  
  38.         }  
  39.     }  
  40.     //三星pad  
  41.     public class PadSamsung : IPad  
  42.     {  
  43.         public virtual void Version()  
  44.         {  
  45.             Debug.Log("三星pad");  
  46.         }  
  47.     }  
  48.     #endregion  
  49.  
  50.  
  51.     #region 工厂  
  52.     public interface IFactory  
  53.     {  
  54.         //pad生产线  
  55.         IPad CreatePad();  
  56.         //phone生产线  
  57.         IPhone CreatePhone();  
  58.     }  
  59.   
  60.     //苹果加工厂  
  61.     public class AppleFactory : IFactory  
  62.     {  
  63.         public IPad CreatePad()  
  64.         {  
  65.             return new PadApple();  
  66.         }  
  67.   
  68.         public IPhone CreatePhone()  
  69.         {  
  70.             return new PhoneApple();  
  71.         }  
  72.     }  
  73.     //三星加工厂  
  74.     public class SumsungFactory : IFactory  
  75.     {  
  76.         public IPad CreatePad()  
  77.         {  
  78.             return new PadSamsung();  
  79.         }  
  80.   
  81.         public IPhone CreatePhone()  
  82.         {  
  83.             return new PhoneSamsung();  
  84.         }  
  85.     }  
  86.     #endregion  
  87. }  


 

优点

当我们需要增加一个产品族的时候,我们只需要增加一个工厂,实现其中所有产品的实现就行了。 
抽象工厂的设计,使得我们可以很容易的增加一个产品系列。

缺点

抽象工厂当中,产品族的定义使得子类必须去实现所有的产品生产。 
因此,抽象工厂并不适合于横向扩展,即需要增加产品的情况。 
一旦需要增加产品,那么我们甚至需要去修改抽象的基类。这是比较违反开闭原则,不太符合面向对象设计的做法。

总结

从简单工厂到工厂方法再到抽象工厂。我们可以看到,抽象的程度越来越高,能够解决的问题也越来越复杂。 
不过,个人的经验而言,一般在unity3d当中也顶多用到工厂方法而已。抽象工厂事实上并不是一个很灵活的解决方案。 
而且,对于unity3d中组件的创建,事实上是有一些非常灵活的解决方案可以处理的。实体与组件系统,相当适合于组件的构建,比起工厂方法来说更加灵活和易于扩展。

 
posted @ 2017-06-29 00:11  三页菌  阅读(172)  评论(0编辑  收藏  举报