設計模式具體應用
大话设计模式中的利用反射加抽象工厂的数据访问程序。先来看看反射技术的基本格式:--反射工廠
Assembly.Load(“程序集名称”).CreateInstance(“命名空间.类名称”);
只要在程序顶端写上using System.Reflection来引用Reflection,就可以采用反射工厂来克服抽象工厂模式的先天不足。下面我们来看通过反射技术实现不同数据库的访问程序.
DataAccess类,用反射技术,取代了抽象工厂中的IFactory,SqlServerFactory和AccessFactory。
具体代码:
- public class User
- {
- private int _id;
- public int ID
- {
- get { return _id; }
- set { _id = value; }
- }
- private string _name;
- public string Name
- {
- get { return _name; }
- set { _name = value; }
- }
- }
- public class Department
- {
- private int _id;
- public int ID
- {
- get { return _id; }
- set { _id = value; }
- }
- private string _deptName;
- public string DeptName
- {
- get { return _deptName; }
- set { _deptName = value; }
- }
- }
- public interface IUser
- {
- void Insert(User user);
- User GetUser(int id);
- }
- public class SqlserverUser : IUser
- {
- public void Insert(User user)
- {
- Console.WriteLine("在Sqlserver中给User表增加一条记录");
- }
- public User GetUser(int id)
- {
- Console.WriteLine("在Sqlserver中根据ID得到User表一条记录");
- return null;
- }
- }
- public class AccessUser : IUser
- {
- public void Insert(User user)
- {
- Console.WriteLine("在Access中给User表增加一条记录");
- }
- public User GetUser(int id)
- {
- Console.WriteLine("在Access中根据ID得到User表一条记录");
- return null;
- }
- }
- public interface IDepartment
- {
- void Insert(Department department);
- Department GetDepartment(int id);
- }
- public class SqlserverDepartment : IDepartment
- {
- public void Insert(Department department)
- {
- Console.WriteLine("在Sqlserver中给Department表增加一条记录");
- }
- public Department GetDepartment(int id)
- {
- Console.WriteLine("在Sqlserver中根据ID得到Department表一条记录");
- return null;
- }
- }
- public class AccessDepartment : IDepartment
- {
- public void Insert(Department department)
- {
- Console.WriteLine("在Access中给Department表增加一条记录");
- }
- public Department GetDepartment(int id)
- {
- Console.WriteLine("在Access中根据ID得到Department表一条记录");
- return null;
- }
- }
- public class DataAccess
- {
- private static readonly string AssemblyName = "抽象工厂模式";
- private static readonly string db = "Sqlserver";
- //private static readonly string db = "Access";
- public static IUser CreateUser()
- {
- string className = AssemblyName + "." + db + "User";
- return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
- }
- public static IDepartment CreateDepartment()
- {
- string className = AssemblyName + "." + db + "Department";
- return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
- }
- }
调用代码:
- User user = new User();
- Department dept = new Department();
- IUser iu = DataAccess.CreateUser();
- iu.Insert(user);
- iu.GetUser(1);
- IDepartment id = DataAccess.CreateDepartment();
- id.Insert(dept);
- id.GetDepartment(1);
- Console.Read();
- }
现在我们要增加Oracle数据访问,相关类的增加是不可避免的,这点是无论我们用什么方法都解决不了的,这是扩展,依照开发-封闭原则,对于扩展,我们开放,但对与修改我们关闭。就现在的代码中,我们要换Oracle很容易,只需将db=”Sqlserver”换成db=”Oracle”。
现在我们需要增加Product,只需增加三个与Product相关的类,再修改一下DataAccess,在其中增加一个创建Product的方法就可以了。
现在我们要更换数据访问程序是,我们还需要修改程序,重新编译,我们可以利用配置文件来解决这个问题,首先要在我们的项目中添加config文件,内容如下:
- <?xml version="1.0" encoding="utf-8" ?>
- <configuration>
- <appSettings>
- <add key="DB" value="Sqlserver"/>
- </appSettings>
- </configuration>
再在项目中引用System.configuration,并在程序头增加using System.configuration;, 然后修改DataAccess类的字段db的赋值代码:
- class DataAccess
- {
- private static readonly string AssemblyName = "抽象工厂模式";
- private static readonly string db = ConfigurationManager.AppSettings["DB"];
- public static IUser CreateUser()
- {
- string className = AssemblyName + "." + db + "User";
- return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
- }
- public static IDepartment CreateDepartment()
- {
- string className = AssemblyName + "." + db + "Department";
- return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
- }
- }
3.总结
使用反射工厂的优点是极大的减少了工厂类的数量,降低了代码的冗余,并且系统更容易扩展,增加新类型后,不需要修改工厂类。
使用反射工厂的代价是工厂与产品之间的依赖关系不明显,由于动态绑定,因此理论上可以用一个工厂完成很多类型的实例化,从而使得代码不容易理解。另外就是增加了测试难度,因为创建是动态完成的。
采用反射技术创建的反射工厂可以使系统更灵活,使工厂和产品之间的依赖关系更小。在.NET的项目中大量的使用了反射工厂取代的传统的工厂。