1. 什么是抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
使用多数据库的代码如下(抽象工厂模式实现)
using System;
using System.Collections.Generic;
using System.Text;
namespace 抽象工厂模式
{
class Program
{
static void Main(string[] args)
{
User user = new User();
Department dept = new Department();
//AbstractFactory 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();
}
}
}
2. 抽象工厂模式的结构图
3. 抽象工厂模式的优点与缺点
易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置;另外,它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
抽象工厂模式的缺点同样很明显,一旦需要增加新的功能时,就需要增加新的抽象产品类与新的具体产品类,同时需要对抽象工厂类与具体工厂类进行更改;另外,可能有很多地方都在使用具体工厂类,如果更改使用的数据库,那么这些地方同样需要更改。
4. 简单改进
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
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";
//private static readonly string db = "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;
}
}
}
改进后删除了程序中的多个工厂类,仅留下一个(简单工厂),这样只需要客户端调用唯一工厂类来生成具体的数据库实例,客户端代码中没有出现具体的数据库名称,达到了解耦的目的。但如果需要增加新的数据库时必须要对代码中的大量switch进行更改。
5. 反射
反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能成为反射。
可以参考这篇 https://blog.csdn.net/lwl20140904/article/details/80163880
C++实现反射 https://blog.csdn.net/zhangqi_gsts/article/details/53395297
https://blog.csdn.net/twd_1991/article/details/80689558
6. 控制反转(Inversion of Control)与依赖注入(Dependency Injection)
这篇文章讲的很详细 https://blog.csdn.net/sinat_21843047/article/details/80297951
7. 反射 + 抽象工厂
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
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);
}
}
}
我们也可以使用配置文件来解决数据库的更改问题。