抽象工厂模式
2009-06-24 16:43
127 查看
定义:
抽象工厂模式是一种创建型模式,意图是“提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类”。(《Design Patterns》GOF)
逻辑:
项目需求:
现在我们要设计一个人事管理系统(PESY),因为该项目需要向很多的单位提供,我们在数据库方面考虑使用SQL SERVER来设计。现在来看看其中数据方面的一些实现。
public class SqlEmployee
{
/// <summary>
/// 查询一个员工的信息
/// </summary>
public EmployeeModel Select(string employeeId)
{
//......SQL SERVER操作
return new EmployeeModel();
}
/// <summary>
/// 删除一个员工
/// </summary>
public bool Delete(string employeeId)
{
//.....SQL SERVER操作
return true;
}
}
/// <summary>
/// 客户调用
/// </summary>
public class PESY
{
public static void Main(string[] args)
{
SqlEmployee employee = new SqlEmployee();
employee.Delete("010101");//删除一个员工人事信息。
}
}
我们知道,不同的数据库的SQL语句会有一些不同,有的数据库可以使用存储过程,视图等等,而有的数据库不支持。
下面我们的需求改变了,一个省级人事机构要使用我们的项目,数据量和更新相当的大,这样我们得考虑到使用大型的关系型数据库,这里我们使用Oracle来改变需求。
public class OracleEmployee
{
/// <summary>
/// 查询一个员工的信息
/// </summary>
public EmployeeModel Select(string employeeId)
{
//......Oracle操作
return new EmployeeModel();
}
/// <summary>
/// 删除一个员工
/// </summary>
public bool Delete(string employeeId)
{
//.....Oracle操作
return true;
}
}
/// <summary>
/// 客户调用
/// </summary>
public class PESY
{
public static void Main(string[] args)
{
OracleEmployee employee = new OracleEmployee();
employee.Delete("010101");//删除一个员工人事信息。其实应该有很多的客户操作。
}
}
很好,看上去我们已经满足了客户的需求。但是如果我们需要更多的数据库类型,就的编写不同数据库操作层,最让我们无法接受的是,我们每次必须去重写
客户端的调用方法,我们不得不每次都委派技术人员到给客户进行调试,客户无法自己进行相关配置,这已经违背的我们学习设计模式的初衷。
那么让我们在仔细分析一下我们的系统。
当每次客户需求改变时,我们就需要考虑数据库是否能够承受客户的需求。目前需求冲突的部分是我们每次都必须修改客户调用部分。我们每次都要为客户进行部署。但是我们发现,在数据库操作层里,他们都用相同的方法名,相同的公共属性,那么我们可能想到可以提取这些接口。
public interface IEmployee
{
EmployeeModel Select(string employeeId);
bool Delete(string employeeId);
}
然后其余的数据库操作类实现这个接口,这样我们就同一类面向接口编程的模型。在来看看我们的客户端现在应该怎么写。
/// <summary>
/// 客户调用
/// </summary>
public class PESY
{
public static void Main(string[] args)
{
IEmployee employee = new SqlEmployee();
employee.Delete("010101");//删除一个员工人事信息。
}
}
我们提取了公共的接口,但是发现好像并没有像我们想想中的一样解决什么问题。因为我们一旦改变的数据库,我们仍然需要改变客户端调用,进行部署。现在我们可以考虑为项目增加一个Factory工厂类。
public class Factory
{
public static IEmployee CreateEmployee()
{
return new SqlEmployee();
}
}
再来看看客户端的调用
/// <summary>
/// 客户调用
/// </summary>
public class PESY
{
public static void Main(string[] args)
{
IEmployee employee = Factory.CreateEmployee();
employee.Delete("010101");//删除一个员工人事信息。
}
}
好像我们已经解决了一个很大的问题,现在如果需求改变为另外一个数据库,就不用在重新部署客户端的调用部分,而只用简单的改变factory里的返
回类。但是我们真正项目的factory可定不会像例子里这么少的一个对象,也许会有几十个,随着系统的升级,甚至可能会增加到几百个。如果我们每次需求
改变都需要这样一个一个来替换,那是多么烦人的一件事情,让我们来解决这个问题,重写这个factory,这里会使用到.NET的反射机制,和配置文件。
public class Factory
{
private static readonly string path = ConfigurationManager.AppSettings["DAL"];
public static IEmployee CreateEmployee()
{
string className = path + ".Employee";
return (IEmployee)Assembly.Load(path).CreateInstance(className); //通过反射机制来动态加载
}
}
配置文件
<appSettings>
<add key="DAL" value="PESY.SQLServerDAL"/>
</appSettings>
这里每次我们只需要在配置文件里指定需要加载的DLL就OK了,现在如果客户需求改变,我们只需要把相应数据库操作类提供给客户,然后更改一下配置就完成了项目,这是不是很奇妙?
总结:为什么把Abstract
Factory放在第一个类写,因为抽象工厂模式是面向接口编程的,这也是面向对象编程的精华部分。其实我这个例子在抽象工厂中应该还存在一些抽象的公共
方法,例如计算员工的工资等等,这些都是可行的。不过我认为现在的例子也已经能够完全表现出面向接口编程的工厂模式。太多太复杂的逻辑反倒让整个思路很杂
乱。大家不妨下载微软的一个.NET示例PetShop4.0,里面对工厂模式使用颇多。最后总结一点,抽象工厂模式主要是解决项目中的对象创建,我们通
常使用工厂模式来封装同类的对象创建。
抽象工厂模式是一种创建型模式,意图是“提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类”。(《Design Patterns》GOF)
逻辑:
项目需求:
现在我们要设计一个人事管理系统(PESY),因为该项目需要向很多的单位提供,我们在数据库方面考虑使用SQL SERVER来设计。现在来看看其中数据方面的一些实现。
public class SqlEmployee
{
/// <summary>
/// 查询一个员工的信息
/// </summary>
public EmployeeModel Select(string employeeId)
{
//......SQL SERVER操作
return new EmployeeModel();
}
/// <summary>
/// 删除一个员工
/// </summary>
public bool Delete(string employeeId)
{
//.....SQL SERVER操作
return true;
}
}
/// <summary>
/// 客户调用
/// </summary>
public class PESY
{
public static void Main(string[] args)
{
SqlEmployee employee = new SqlEmployee();
employee.Delete("010101");//删除一个员工人事信息。
}
}
我们知道,不同的数据库的SQL语句会有一些不同,有的数据库可以使用存储过程,视图等等,而有的数据库不支持。
下面我们的需求改变了,一个省级人事机构要使用我们的项目,数据量和更新相当的大,这样我们得考虑到使用大型的关系型数据库,这里我们使用Oracle来改变需求。
public class OracleEmployee
{
/// <summary>
/// 查询一个员工的信息
/// </summary>
public EmployeeModel Select(string employeeId)
{
//......Oracle操作
return new EmployeeModel();
}
/// <summary>
/// 删除一个员工
/// </summary>
public bool Delete(string employeeId)
{
//.....Oracle操作
return true;
}
}
/// <summary>
/// 客户调用
/// </summary>
public class PESY
{
public static void Main(string[] args)
{
OracleEmployee employee = new OracleEmployee();
employee.Delete("010101");//删除一个员工人事信息。其实应该有很多的客户操作。
}
}
很好,看上去我们已经满足了客户的需求。但是如果我们需要更多的数据库类型,就的编写不同数据库操作层,最让我们无法接受的是,我们每次必须去重写
客户端的调用方法,我们不得不每次都委派技术人员到给客户进行调试,客户无法自己进行相关配置,这已经违背的我们学习设计模式的初衷。
那么让我们在仔细分析一下我们的系统。
当每次客户需求改变时,我们就需要考虑数据库是否能够承受客户的需求。目前需求冲突的部分是我们每次都必须修改客户调用部分。我们每次都要为客户进行部署。但是我们发现,在数据库操作层里,他们都用相同的方法名,相同的公共属性,那么我们可能想到可以提取这些接口。
public interface IEmployee
{
EmployeeModel Select(string employeeId);
bool Delete(string employeeId);
}
然后其余的数据库操作类实现这个接口,这样我们就同一类面向接口编程的模型。在来看看我们的客户端现在应该怎么写。
/// <summary>
/// 客户调用
/// </summary>
public class PESY
{
public static void Main(string[] args)
{
IEmployee employee = new SqlEmployee();
employee.Delete("010101");//删除一个员工人事信息。
}
}
我们提取了公共的接口,但是发现好像并没有像我们想想中的一样解决什么问题。因为我们一旦改变的数据库,我们仍然需要改变客户端调用,进行部署。现在我们可以考虑为项目增加一个Factory工厂类。
public class Factory
{
public static IEmployee CreateEmployee()
{
return new SqlEmployee();
}
}
再来看看客户端的调用
/// <summary>
/// 客户调用
/// </summary>
public class PESY
{
public static void Main(string[] args)
{
IEmployee employee = Factory.CreateEmployee();
employee.Delete("010101");//删除一个员工人事信息。
}
}
好像我们已经解决了一个很大的问题,现在如果需求改变为另外一个数据库,就不用在重新部署客户端的调用部分,而只用简单的改变factory里的返
回类。但是我们真正项目的factory可定不会像例子里这么少的一个对象,也许会有几十个,随着系统的升级,甚至可能会增加到几百个。如果我们每次需求
改变都需要这样一个一个来替换,那是多么烦人的一件事情,让我们来解决这个问题,重写这个factory,这里会使用到.NET的反射机制,和配置文件。
public class Factory
{
private static readonly string path = ConfigurationManager.AppSettings["DAL"];
public static IEmployee CreateEmployee()
{
string className = path + ".Employee";
return (IEmployee)Assembly.Load(path).CreateInstance(className); //通过反射机制来动态加载
}
}
配置文件
<appSettings>
<add key="DAL" value="PESY.SQLServerDAL"/>
</appSettings>
这里每次我们只需要在配置文件里指定需要加载的DLL就OK了,现在如果客户需求改变,我们只需要把相应数据库操作类提供给客户,然后更改一下配置就完成了项目,这是不是很奇妙?
总结:为什么把Abstract
Factory放在第一个类写,因为抽象工厂模式是面向接口编程的,这也是面向对象编程的精华部分。其实我这个例子在抽象工厂中应该还存在一些抽象的公共
方法,例如计算员工的工资等等,这些都是可行的。不过我认为现在的例子也已经能够完全表现出面向接口编程的工厂模式。太多太复杂的逻辑反倒让整个思路很杂
乱。大家不妨下载微软的一个.NET示例PetShop4.0,里面对工厂模式使用颇多。最后总结一点,抽象工厂模式主要是解决项目中的对象创建,我们通
常使用工厂模式来封装同类的对象创建。
相关文章推荐
- 设计模式读书笔记之抽象工厂模式(Abstract Factory)
- 三 抽象工厂模式
- 设计模式C++学习笔记之七(AbstractFactory抽象工厂模式)
- 23种设计模式(3):抽象工厂模式
- Java设计模式之工厂方法、抽象工厂模式 程序 总结
- 大话设计模式java版--抽象工厂模式
- 使用Object-C实现23种设计模式之抽象工厂模式
- Java设计模式(三):工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)
- 设计模式总纲——抽象工厂模式
- C# 设计模式系列教程-抽象工厂模式
- java设计模式之抽象工厂模式学习
- 抽象工厂模式
- 设计模式-抽象工厂模式
- 设计模式之抽象工厂模式
- 抽象工厂模式(三)
- 找女朋友之简单工厂模式,工厂模式,抽象工厂模式
- 设计模式(2)-创建型-简单工厂,工厂,抽象工厂模式(Factory)
- 设计模式之抽象工厂模式
- 抽象工厂模式的认识和学习(含学习案例)
- 工厂模式:简单工厂模式、工厂方法模式、抽象工厂模式