就不能换DB吗? 抽象工厂模式
15.1 就不能换DB吗?
15.2 最基本的数据访问程序
namespace 抽象工厂模式 { class Program { static void Main(string[] args) { User user = new User(); SqlserverUser su = new SqlserverUser(); //与SQLServer耦合, su.Insert(user); su.GetUser(1); Console.Read(); } } //用户类, 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; } } } //操作User表类, class SqlserverUser { //新增用户, public void Insert(User user) { Console.WriteLine("在Sqlserver中给User表增加一条记录"); } //得到用户, public User GetUser(int id) { Console.WriteLine("在Sqlserver中根据ID得到User表一条记录"); return null; } } }
15.3 用了工厂方法模式的数据访问程序
namespace 抽象工厂模式 { class Program { static void Main(string[] args) { User user = new User(); //IFactory factory = new SqlServerFactory(); IFactory factory = new AccessFactory(); IUser iu = factory.CreateUser(); iu.Insert(user); iu.GetUser(1); Console.Read(); } } 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; } } } //IUser接口,用于客户端访问,解除与具体数据库的耦合, interface IUser { void Insert(User user); User GetUser(int id); } //SqlserverUser类,用于访问SQLServer的User, class SqlserverUser : IUser { public void Insert(User user) { Console.WriteLine("在Sqlserver中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Sqlserver中根据ID得到User表一条记录"); return null; } } //AccessUser类,用于访问Access的User, class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("在Access中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Access中根据ID得到User表一条记录"); return null; } } //IFactory接口,定义一个创建访问User表对象的抽象的工厂接口, interface IFactory { IUser CreateUser(); } //SqlServerFactory类,实现IFactory接口,实例化SqlserverUser, class SqlServerFactory : IFactory { public IUser CreateUser() { return new SqlserverUser(); } } //AccessFactory类,实现IFactory接口,实例化AccessUser, class AccessFactory : IFactory { public IUser CreateUser() { return new AccessUser(); } } }
15.4 用了抽象工厂模式的数据访问程序
namespace 抽象工厂模式 { class Program { static void Main(string[] args) { User user = new User(); Department dept = new Department(); //IFactory factory = new SqlServerFactory(); IFactory factory = new AccessFactory(); IUser iu = factory.CreateUser(); iu.Insert(user); iu.GetUser(1); IDepartment id = factory.CreateDepartment(); id.Insert(dept); id.GetDepartment(1); Console.Read(); } } 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; } } } 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; } } } interface IUser { void Insert(User user); User GetUser(int id); } class SqlserverUser : IUser { public void Insert(User user) { Console.WriteLine("在Sqlserver中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Sqlserver中根据ID得到User表一条记录"); return null; } } class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("在Access中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Access中根据ID得到User表一条记录"); return null; } } interface IDepartment { void Insert(Department department); Department GetDepartment(int id); } class SqlserverDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Sqlserver中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Sqlserver中根据ID得到Department表一条记录"); return null; } } class AccessDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Access中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Access中根据ID得到Department表一条记录"); return null; } } interface IFactory { IUser CreateUser(); IDepartment CreateDepartment(); } class SqlServerFactory : IFactory { public IUser CreateUser() { return new SqlserverUser(); } public IDepartment CreateDepartment() { return new SqlserverDepartment(); } } class AccessFactory : IFactory { public IUser CreateUser() { return new AccessUser(); } public IDepartment CreateDepartment() { return new AccessDepartment(); } } }
15.5 抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类,
namespace 抽象工厂模式 { class Program { static void Main(string[] args) { AbstractFactory factory1 = new ConcreteFactory1(); Client c1 = new Client(factory1); c1.Run(); AbstractFactory factory2 = new ConcreteFactory2(); Client c2 = new Client(factory2); c2.Run(); Console.Read(); } } //抽象产品A, abstract class AbstractProductA { //它们可以有不同的实现, } //抽象产品B, abstract class AbstractProductB { public abstract void Interact(AbstractProductA a); } //对两个抽象产品A和B的具体分类的实现, class ProductA1 : AbstractProductA { } //对两个抽象产品A和B的具体分类的实现, class ProductB1 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } //对两个抽象产品A和B的具体分类的实现, class ProductA2 : AbstractProductA { } //对两个抽象产品A和B的具体分类的实现, class ProductB2 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } //抽象工厂接口,包含所有产品创建的抽象方法, abstract class AbstractFactory { public abstract AbstractProductA CreateProductA(); public abstract AbstractProductB CreateProductB(); } //具体工厂, class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA1(); } public override AbstractProductB CreateProductB() { return new ProductB1(); } } //具体工厂, class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() //运行时创建ConcreteFactory类的实例,具体的工厂再创建具有特定实现的产品对象, { //即创建不同的产品对象,客户端应使用不同的具体工厂, return new ProductA2(); } public override AbstractProductB CreateProductB() { return new ProductB2(); } } class Client { private AbstractProductA AbstractProductA; private AbstractProductB AbstractProductB; public Client(AbstractFactory factory) { AbstractProductB = factory.CreateProductB(); AbstractProductA = factory.CreateProductA(); } public void Run() { AbstractProductB.Interact(AbstractProductA); } } }
15.6 抽象工厂模式的优点与缺点
优点:最大的好处便是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置,第二大好处是,它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中,
缺点:抽象工厂模式可以很方便的切换两个数据库访问的代码,但如果你的需求来自增加功能,如增加项目表Project,需要改动哪些部分?至少增加三个类,IProject,SqlserverProject,AccessProject,需更改三个类,IFactory,SqlserverFactory,AccessFactory,并且客户端程序显然不会只有一个,如果有100个调用数据库访问的类,是不是要更改100次 IFactory factory = new AccessFactory( ); 这样的代码才行呢?这不能解决我要更改数据库时,改动一处就完全更改的要求阿,
15.7 用简单工厂来改进抽象工厂
namespace 抽象工厂模式 { class Program { static void Main(string[] args) { 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(); } } 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; } } } 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; } } } interface IUser { void Insert(User user); User GetUser(int id); } class SqlserverUser : IUser { public void Insert(User user) { Console.WriteLine("在Sqlserver中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Sqlserver中根据ID得到User表一条记录"); return null; } } class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("在Access中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Access中根据ID得到User表一条记录"); return null; } } interface IDepartment { void Insert(Department department); Department GetDepartment(int id); } class SqlserverDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Sqlserver中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Sqlserver中根据ID得到Department表一条记录"); return null; } } class AccessDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Access中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Access中根据ID得到Department表一条记录"); return null; } } class DataAccess { private static readonly string db = "Sqlserver"; //与其用IFactory,SqlserverFactory,AccessFactory三个工厂类, //private static readonly string db = "Access"; //不如直接用一个简单工厂来实现,DataAccess类取而代之它们, //客户端没有出现任何一个SQLServer或Access的字样,达到了解耦的目的, public static IUser CreateUser() //客户端已经不在受改动数据库访问的影响了, { //但增加数据库访问就麻烦了, IUser result = null; switch (db) { case "Sqlserver": result = new SqlserverUser(); break; case "Access": result = new AccessUser(); break; } return result; } public static IDepartment CreateDepartment() { IDepartment result = null; switch (db) { case "Sqlserver": result = new SqlserverDepartment(); break; case "Access": result = new AccessDepartment(); break; } return result; } } }
15.8 用反射+抽象工厂的数据访问程序
Assembly.Load("程序集名称").CreateInstance("命名空间.类名称");
原来实例化是写死在程序里的,现在用了反射就可以利用字符串来实例化对象,而变量是可以更换的,即变量"db",
namespace 抽象工厂模式 { class Program { static void Main(string[] args) { 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(); } } 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; } } } 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; } } } interface IUser { void Insert(User user); User GetUser(int id); } class SqlserverUser : IUser { public void Insert(User user) { Console.WriteLine("在Sqlserver中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Sqlserver中根据ID得到User表一条记录"); return null; } } class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("在Access中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Access中根据ID得到User表一条记录"); return null; } } interface IDepartment { void Insert(Department department); Department GetDepartment(int id); } class SqlserverDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Sqlserver中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Sqlserver中根据ID得到Department表一条记录"); return null; } } class AccessDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Access中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Access中根据ID得到Department表一条记录"); return null; } } 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); } } }
15.9 用反射+配置文件的数据访问程序
namespace 抽象工厂模式 { class Program { static void Main(string[] args) { 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(); } } 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; } } } 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; } } } interface IUser { void Insert(User user); User GetUser(int id); } class SqlserverUser : IUser { public void Insert(User user) { Console.WriteLine("在Sqlserver中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Sqlserver中根据ID得到User表一条记录"); return null; } } class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("在Access中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Access中根据ID得到User表一条记录"); return null; } } interface IDepartment { void Insert(Department department); Department GetDepartment(int id); } class SqlserverDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Sqlserver中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Sqlserver中根据ID得到Department表一条记录"); return null; } } class AccessDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Access中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Access中根据ID得到Department表一条记录"); return null; } } 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); } } }
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="DB" value="Access"/> </appSettings> </configuration>
15.10 无痴迷 不成功