抽象工厂模式:
抽象工厂(Abstract Factory): 提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体类。
结构图:
AbstractProductA 和 AbstractProductB 是两个抽象产品 之所以是抽象,是因为它们都有可能又两种不同的实现。而 ProductA1,ProductA2和ProductB1,ProductB2 就是对两个抽象产品的具体分类的实现。 比如 ,ProductA1 可以理解为 SqlServer 某个表对应的实体数据。而 ProductA2可以理解为 Oracle 中某个表对应的实体数据。
IFactroy 是一个 抽象工厂的接口,它里面包含了所有产品创建的抽象方法。 而 Concretefactory1 和 Concretefactory2 就是具体的工厂。 通常在运行时刻在创建一个ConcreteFactory 类的实例,这个 工厂在创建具有特定实现的产品对象 。也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂。
抽象工厂的优点与缺点:
优点:
1:最大的好处便于交换产品系列,由于具体工厂类,例如:IFactory factory= new OracleFactory()
,在一个应用中只需要在初始化的时候出现一次,这使得改变一个 应用的具体共产变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。我们的 设计不能去 防止需求的改动,那我们的理想就是让改动变得最小,现在如果你需要更改数据库访问,我们只需要更改具体工厂就可以做到。
2:它让具体的创建实例过程与客户端分离,客户端是通过它的抽象接口操纵实例,产品具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
缺点:
1:新增功能或数据实体CRUD时,需要 改动的地方很多 。
2:客户端每一次调用 都需要创建一个 工厂接口实例。
解决上面两个缺点:反射+配置文件
代码演示:
对象模型
namespace 抽象工厂.Model
{
/// <summary>
/// 实体模型
/// </summary>
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
对象方法接口
namespace 抽象工厂.Interfac
{
public interface IUser
{
void Insert(User user);
User GetUser(int id);
}
}
不同数据库接口实现
namespace 抽象工厂.DB
{
public class AccessUser : IUser
{
public User GetUser(int id)
{
Console.WriteLine("在 Access 中根据用户ID 获取一条用户信息");
return null;
}
public void Insert(User user)
{
Console.WriteLine("在 Access 中添加一条 user 用户信息");
}
}
}
namespace 抽象工厂.DB
{
public class SqlServerUser : IUser
{
public User GetUser(int id)
{
Console.WriteLine("在 SQL Server 根据ID 获取一条用户信息 ");
return null;
}
public void Insert(User user)
{
Console.WriteLine("在 SQL Server 中插入一条用户 User 信息");
}
}
}
抽象工厂
namespace 抽象工厂.Factory
{
public interface IFactory
{
IUser CreateUser();
}
}
namespace 抽象工厂.Factory
{
public class AccessFactory : IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
}
}
namespace 抽象工厂.Factory
{
public class SqlServerFactory : IFactory
{
public IUser CreateUser()
{
return new SqlServerUser();
}
}
}
调用:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using 抽象工厂.DB;
using 抽象工厂.Factory;
using 抽象工厂.Interfac;
using 抽象工厂.Model;
namespace 抽象工厂
{
class Program
{
static void Main(string[] args)
{
string db = ConfigurationManager.AppSettings["db"];//配置文件,配置数据库
string Model = db + "User";
IUser u=(IUser)Assembly.Load("抽象工厂").CreateInstance("抽象工厂.DB."+Model);//反射,加载具体实现类
u.Insert(user);
u.GetUser(1);
Console.ReadKey();
}
}
}