抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体的类。
【为创建不同的产品对象,客户端应使用不同的具体工厂】
通俗理解:我们可以理解成:一台电脑。最基本的配件:CPU、主板、内存、硬盘【所定义的接口】,不同配置的电脑,则需要不同的类进行实现。
举个例子,数据库访问的例子。
定义数据库类:User、Department
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class User 10 { 11 private int _id; 12 public int ID 13 { 14 get { return _id; } 15 set { _id = value; } 16 } 17 private string _name; 18 public string Name 19 { 20 get { return _name; } 21 set { _name = value; } 22 } 23 } 24 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class Department 10 { 11 private int _id; 12 public int ID 13 { 14 get { return _id; } 15 set { _id = value; } 16 } 17 private string _deptname; 18 public string DeptName 19 { 20 get { return _deptname; } 21 set { DeptName = value; } 22 } 23 } 24 }
定义User、Department接口
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 interface IUser 10 { 11 void Insert(User user); 12 User GetUser(int id); 13 } 14 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 interface IDepartment 10 { 11 void Inster(Department department); 12 Department GetDepartment(int id); 13 } 14 }
SqlserverUser类,用于访问SQL Server 的 User
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class SQLServerUser : IUser 10 { 11 public void Insert(User user) 12 { 13 Console.WriteLine("在SQL Server 中给User表增加一条记录"); 14 } 15 public User GetUser(int id) 16 { 17 Console.WriteLine("在SQL Server 中根据ID得到User表一条记录"); 18 return null; 19 } 20 } 21 }
AccessUser类,用于访问Access的User
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class AccessDepartment : IDepartment 10 { 11 public Department GetDepartment(int id) 12 { 13 Console.WriteLine("在Access 中给Department表增加一条记录"); 14 return null; 15 } 16 17 public void Inster(Department department) 18 { 19 Console.WriteLine("在Access 中根据ID得到Department表一条记录"); 20 } 21 } 22 }
SQLDepartment类,用于访问SQL Server 的 Department
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class SQLDepartment : IDepartment 10 { 11 public void Inster(Department department) 12 { 13 Console.WriteLine("在SQL Server 中给Department表增加一条记录"); 14 } 15 16 public Department GetDepartment(int id) 17 { 18 Console.WriteLine("在SQL Server 中根据ID得到Department表一条记录"); 19 return null; 20 } 21 } 22 }
AccessDepartment 类,用于访问Access的Department
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class AccessDepartment : IDepartment 10 { 11 public Department GetDepartment(int id) 12 { 13 Console.WriteLine("在Access 中给Department表增加一条记录"); 14 return null; 15 } 16 17 public void Inster(Department department) 18 { 19 Console.WriteLine("在Access 中根据ID得到Department表一条记录"); 20 } 21 } 22 }
IFactory接口。定义一个创建访问User、Department 表对象的抽象的工厂接口。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 interface IFactory 10 { 11 IUser CreaterUser(); 12 IDepartment CreateDepartment(); 13 } 14 }
SqlServerFactory类,实现IFactory,实例化SqlserverUser和SqlserverDepartment
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class SQLFactory : IFactory 10 { 11 public IDepartment CreateDepartment() 12 { 13 return new SQLDepartment(); 14 } 15 16 public IUser CreaterUser() 17 { 18 return new SQLServerUser(); 19 } 20 } 21 }
AccessFactory类,实现IFactory接口,实例化AccessUser和AccessDepartMent
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class AccessFactory : IFactory 10 { 11 public IDepartment CreateDepartment() 12 { 13 return new AccessDepartment(); 14 } 15 16 public IUser CreaterUser() 17 { 18 return new AccessUser(); 19 } 20 } 21 }
客户端代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式02 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 User user = new User(); 14 Department dept = new Department(); 15 16 IFactory factory = new AccessFactory(); 17 IUser iu = factory.CreaterUser(); 18 iu.Insert(user); 19 iu.GetUser(1); 20 21 IDepartment id = factory.CreateDepartment(); 22 id.Inster(dept); 23 id.GetDepartment(1); 24 25 Console.ReadLine(); 26 } 27 } 28 }
使用简单工厂来改进抽象工厂
上面的例子中,每一个类开始都需要 IFactory factory = new AccessFactory(),如果有100个调用数据库的访问类,同时就要修改100次 ,IFactory factory = new AccessFactory(),这是非常不合理的
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式03 8 { 9 class DataAccess 10 { 11 private static readonly string db = "Access"; 12 public static IUser CreateUser() 13 { 14 IUser result = null; 15 switch(db) 16 { 17 case "SQL": 18 result = new SQLServerUser(); 19 break; 20 case "Access": 21 result = new AccessUser(); 22 break; 23 } 24 return result; 25 } 26 27 public static IDepartment CreateDepartment() 28 { 29 IDepartment result = null; 30 switch (db) 31 { 32 case "SQL": 33 result = new SQLDepartment(); 34 break; 35 case "Access": 36 result = new AccessDepartment(); 37 break; 38 } 39 return result; 40 } 41 } 42 }
客户端代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式03 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 User user = new User(); 14 Department dept = new Department(); 15 IUser iu = DataAccess.CreateUser(); 16 iu.Insert(user); 17 iu.GetUser(1); 18 19 IDepartment id = DataAccess.CreateDepartment(); 20 id.Inster(dept); 21 id.GetDepartment(1); 22 Console.ReadLine(); 23 } 24 } 25 }
通过反射+抽象工厂优化数据库访问
我们还可以通过反射的方式,进行优化
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Reflection; 7 8 namespace _15抽象工厂模式04 9 { 10 class DataAccess 11 { 12 private static readonly string AssemblyName = "15抽象工厂模式04"; 13 private static readonly string db = "SQLServer"; 14 public static IUser CreateUser() 15 { 16 string classname = "_" + AssemblyName + "." + db + "User"; 17 Assembly s = Assembly.Load(AssemblyName); 18 //Type[] type = s.GetTypes(); 19 IUser us = (IUser)Assembly.Load(AssemblyName).CreateInstance(classname); ; 20 return us; 21 } 22 23 public static IDepartment CreateDepartment() 24 { 25 string classname = "_" + AssemblyName + "." + db + "Department"; 26 Assembly s = Assembly.Load(AssemblyName); 27 Type[] type = s.GetTypes(); 28 return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(classname); 29 } 30 } 31 }
客户端代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _15抽象工厂模式04 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 User user = new User(); 14 Department dept = new Department(); 15 IUser iu = DataAccess.CreateUser(); 16 iu.Insert(user); 17 iu.GetUser(1); 18 19 IDepartment id = DataAccess.CreateDepartment(); 20 id.Inster(dept); 21 id.GetDepartment(1); 22 Console.ReadLine(); 23 } 24 } 25 }
上述的db字符串。我们也可以通过app.config文件来定义
在使用:ConfigurationManager.AppSettings["db"],来获取所需要的访问的数据库。
简单工厂、工厂模式、抽象工厂模式的区别
1、简单工厂模式:由工厂内部指定具体的实例。仓库指定了只有这几种道具,你只能根据我告诉你的这几种类型中去选择。当你需要道具一的时候,我就给你道具一,如果你需要道具二,而我只能叫你等待:添加新的道具,并放到仓库中。
2、工厂模式:仓库不在存放道具,而是直接告诉你有道具(具体是哪一类道具,并没有说明),这时候你需要道具N,就告诉你去某某道具店拿。
3、抽象工厂模式:可以理解成组装电脑,可以组装成N个功能集合,不同的配置【不同的抽象工厂】,组装成不同配置的电脑【具体的实现类】