抽象工厂模式
抽象工厂模式在工厂方法模式的基础上进行了改进,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
使用抽象工厂模式实现数据库切换例子如下:
首先定义两个对象的接口和它的多个具体的实现
public interface IUser { void Insert(string name); IUser GetUser(int id); } public interface IDepartment { void Insert(string name); IDepartment GetDept(int id); } public class SQLServerUser : IUser { #region IUser 成员 public void Insert(string name) { Console.WriteLine("Insert sqlserver user"); } public IUser GetUser(int id) { Console.WriteLine("Get sqlserver user"); return null; } #endregion } public class AccessUser : IUser { #region IUser 成员 public void Insert(string name) { Console.WriteLine("Insert access user"); } public IUser GetUser(int id) { Console.WriteLine("Get access user"); return null; } #endregion } public class SQLServerDepartment : IDepartment { #region IDepartment 成员 public void Insert(string name) { Console.WriteLine("Insert sqlserver department"); } public IDepartment GetDept(int id) { Console.WriteLine("Get sqlserver department"); return null; } #endregion } public class AccessDepartment : IDepartment { #region IDepartment 成员 public void Insert(string name) { Console.WriteLine("Insert access department"); } public IDepartment GetDept(int id) { Console.WriteLine("Get access department"); return null; } #endregion }
然后定义抽象工厂接口,和具体的工厂,具体的工厂负责创建一系列相关的对象
public interface IFactory { IUser UserData(); IDepartment DeptData(); } public class SQLServerFactory : IFactory { #region IFactory 成员 public IUser UserData() { return new SQLServerUser(); } public IDepartment DeptData() { return new SQLServerDepartment(); } #endregion } public class AccessFactory : IFactory { #region IFactory 成员 public IUser UserData() { return new AccessUser(); } public IDepartment DeptData() { return new AccessDepartment(); } #endregion }
客户端使用不同的工厂实例,完成一系列产品对象的创建
//实例化Sqlserver数据库访问对象 //IFactory factory = new SQLServerFactory(); //实例化Access数据库访问对象, 两个工厂对象二选一 IFactory factory = new AccessFactory(); IUser userData = factory.UserData(); userData.Insert("test"); userData.GetUser(1); IDepartment deptData = factory.DeptData(); deptData.Insert("test"); deptData.GetDept(1);
抽象工厂方法的优点是便于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,所以改变一个应用的具体工厂变得非常容易,只需要改变具体工厂即可。
另外,由于它让具体的创建实例过程与客户端分离,客户端是通过抽象借口操纵实例的,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
但是抽象工厂方法在需要初始化很多次的时候则是不便使用的,这是则可以使用简单工厂加配置和反射。
下面将抽象工厂改为简单工厂加配置和反射完成
/// <summary> /// 简单工厂模式结合反射,使用反射避免了switch case 的判断 /// </summary> public class SimplyFactory { private static string assemblyName = "AbstractFactoryModel"; //该字符串可以使用配置文件 private static string dbType = "SQLServer"; public IUser UserData() { IUser userData = (IUser)Assembly.Load(assemblyName).CreateInstance(assemblyName + "." + dbType + "User"); return userData; } public IDepartment DeptData() { IDepartment deptData = (IDepartment)Assembly.Load(assemblyName).CreateInstance(assemblyName + "." + dbType + "Department"); return deptData; } }
在需要更改实例化的对象时,不需要修改代码,而只需要修改配置文件即可,客户端的使用如下:
//实例化时无需制定任何类型,全部由工厂根据配置实现 SimplyFactory factory = new SimplyFactory(); IUser userData = factory.UserData(); IDepartment deptData = factory.DeptData(); userData.Insert("test"); userData.GetUser(1); deptData.Insert("test"); deptData.GetDept(1);
这样,客户端在需要实例化多个工厂的时候,只需要修改配置文件,不需要修改每一个实例化代码。