简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
就以之前玩过的一个游戏为例子,通过简单工厂来实现一系列功能。
首先这个游戏分为5个门派(金,木,水,火,土),每个不同的门派拥有不同的技能。
首先定义一个门派接口,然后分别定义几个实现门派。
/// <summary> /// 门派接口 /// </summary> public interface ISects { /// <summary> /// 技能 /// </summary> void Skill(); }
/// <summary> /// 金系门派 /// </summary> public class Gold : ISects { public void Skill() { Console.WriteLine("金系门派技能:金光乍现"); } }
/// <summary> /// 木系门派 /// </summary> public class Wood : ISects { public void Skill() { Console.WriteLine("木系门派技能:摘叶飞花"); } }
/// <summary> /// 水系门派 /// </summary> public class Water : ISects { public void Skill() { Console.WriteLine("水系门派技能:滴水穿石"); } }
接下来是调用:
ISects gold = new Gold(); gold.Skill(); ISects wood = new Wood(); wood.Skill(); ISects water = new Water(); water.Skill()
我们来看一下结果:
没有意外的得到了我们想要的结果,但是对于我们上端(调用端)而言,我们高度耦合了细节,也就违背了我们开发时经常挂在嘴边的"低耦合",那么现在我们遇到了这种问题,现在当然要来解决了。
1.用简单工厂来解决我们遇到的问题
而"简单工厂"就能很好的解决这类问题。
我们只需要将创建对象这个动作转移到另一个地方即可。
建立一个工厂类,专门为我们生产我们需要的对象。
public class Factory { public static ISects CreateInstance(SectsType sectsType) { switch (sectsType) { case SectsType.Gold: return new Gold(); case SectsType.Wood: return new Wood(); case SectsType.Water: return new Water(); case SectsType.Fire: throw new ArgumentException("没有Fire门派"); case SectsType.Soil: throw new ArgumentException("没有Soil门派"); default: throw new ArgumentException(); } } public enum SectsType { Gold, Wood, Water, Fire, Soil } }
然后调用方式如下:
ISects gold = Factory.CreateInstance(Factory.SectsType.Gold); gold.Skill(); ISects wood = Factory.CreateInstance(Factory.SectsType.Wood); gold.Skill();
结果如下:
上面所示就是用简单工厂很好的解决了我们的问题。
2.简单工厂+配置文件 使得我们的项目变的可配置
配置文件如下:
<appSettings> <add key="SectsTypeName" value="Water"/> </appSettings>
工厂内部创建对象的方法如下:
private static string SectsTypeName = ConfigurationManager.AppSettings["SectsTypeName"]; public static ISects CreateInstanceWithConfig() { switch (Enum.Parse(typeof(SectsType), SectsTypeName)) { case SectsType.Gold: return new Gold(); case SectsType.Wood: return new Wood(); case SectsType.Water: return new Water(); case SectsType.Fire: throw new ArgumentException("没有Fire门派"); case SectsType.Soil: throw new ArgumentException("没有Soil门派"); default: throw new ArgumentException(); } }
结果如下:
3.简单工厂+配置文件+反射 使得我们的项目变得可扩展
配置文件如下:
<appSettings> <add key="SectsTypeNameWithReflect" value="SimpleFactory,SimpleFactory.Wood"/> </appSettings>
工厂类创建对象方法代码如下:
private static string SectsTypeNameWithReflect = ConfigurationManager.AppSettings["SectsTypeNameWithReflect"]; public static ISects CreateInstanceWithReflect() { string assemblyName = SectsTypeNameWithReflect.Split(',')[0]; string typeName = SectsTypeNameWithReflect.Split(',')[1]; return (ISects)Activator.CreateInstance(assemblyName,typeName).Unwrap(); }
调用代码:
ISects wood = Factory.CreateInstanceWithReflect();
wood.Skill();
结果如下:
简单工厂到这里,可所谓是已经非常强大了,当我们需要添加一个新的门派的时候,只需要要添加新的门派类即可,当有一个第三方类库也实现了我们的门派接口时,我们只需要将它的dll拷贝过来就行,然后就可以使用了,这才是真正做到了可扩展。