1.简介
简单工厂模式就是将类的实例化都放在一个工厂类中,用这个类来解耦上层代码
这样的好处比如:当某个类的名字修改了,只需修改工厂类中对应的这个类的名字就可以了
我们模拟魔兽争霸游戏来简单介绍一下
首先,我们建一个接口,用来定义种族动作
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { public interface IRace//接口最好就使用public { void ShowKing(); } }
新建四个类,继承这个接口,表示四个种族
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { class Human : IRace { public void ShowKing() { Console.WriteLine("这里是人类的国王"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { class NE : IRace { public void ShowKing() { Console.WriteLine("这里是精灵族的国王"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { class Orc : IRace { public void ShowKing() { Console.WriteLine("这里是兽族的国王"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { class Undead : IRace { public void ShowKing() { Console.WriteLine("这里是不死族的国王"); } } }
新建一个工厂类,用来实现实例化,把类的实例化从上层代码(这里是Program)转移到这个工厂类中
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { public class Factory { public static IRace GetRace(FactoryType factoryType) { switch(factoryType) { case FactoryType.Human:return new Human(); case FactoryType.NE: return new NE(); case FactoryType.Orc: return new Orc(); case FactoryType.Undead: return new Undead(); default:throw new Exception(); } } } public enum FactoryType { Human, NE, Orc, Undead } }
Program代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { class Program { static void Main(string[] args) { IRace race1 = Factory.GetRace(FactoryType.Human); race1.ShowKing(); IRace race2 = Factory.GetRace(FactoryType.NE); race2.ShowKing(); IRace race3 = Factory.GetRace(FactoryType.Orc); race3.ShowKing(); IRace race4 = Factory.GetRace(FactoryType.Undead); race4.ShowKing(); Console.Read(); } } }
这样,我们就实现了一个简单工厂模式,把Program从细节代码变成抽象代码
若Human、NE、Orc、Undead这些种族类名称发生变化,我们只需要修改工厂类Factory就可以了,也就是把耦合从Program转移到Factory
2.利用配置文件定义类型
在配置文件APP.config中添加AppSetting(配置文件就是一个XML文件)
<appSettings> <add key="Race" value="Human"/> </appSettings>
在工厂类Factory中调用配置文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Configuration;//要添加这个引用 namespace SimpleFactory { public class Factory { public static string race = ConfigurationManager.AppSettings["Race"];//获取配置文件的Race public static IRace GetRace() { FactoryType factoryType = (FactoryType)Enum.Parse(typeof(FactoryType), race);//将Race转换为枚举值 switch (factoryType) { case FactoryType.Human:return new Human(); case FactoryType.NE: return new NE(); case FactoryType.Orc: return new Orc(); case FactoryType.Undead: return new Undead(); default:throw new Exception(); } } } public enum FactoryType { Human, NE, Orc, Undead } }
Program:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { class Program { static void Main(string[] args) { IRace race1 = Factory.GetRace(); race1.ShowKing(); Console.Read(); } } }
这样我们可以通过修改配置文件中的value来使Factory实例化不同的类并返回
3.利用反射对Factory工厂进行解耦
在配置文件APP.config中再添加一个key
<appSettings> <add key="Race" value="Undead"/> <add key="raceReflect" value="SimpleFactory,SimpleFactory.NE"/> </appSettings>
Factory如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Configuration; using System.Reflection; namespace SimpleFactory { public class Factory {//反射实现解耦,不再代码中出现细节 public static string raceReflect = ConfigurationManager.AppSettings["raceReflect"];//获取配置文件的Race public static IRace GetRaceReflect() { //写法一 string assemblyName = raceReflect.Split(',')[0]; string typeName = raceReflect.Split(',')[1]; return (IRace)Activator.CreateInstance(assemblyName, typeName).Unwrap(); //写法二 //string [] raceReflectValue = raceReflect.Split(','); //Assembly assembly = Assembly.Load(raceReflectValue[0]); //Type type = assembly.GetType(raceReflectValue[1]);//基于类的完整名称找出类型 //return (IRace)Activator.CreateInstance(type);//实例化 } } }
Program:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleFactory { class Program { static void Main(string[] args) { Console.WriteLine("-----------------------reflect----------------------------"); IRace race2 = Factory.GetRaceReflect(); race2.ShowKing(); Console.Read(); } } }
使用这种方法,Factory不会再出现Human, NE, Orc, Undead这些细节词,一切基于配置文件
所以,当我们新增一个种族类的时候,只需要修改配置文件就可以调用这个类