这是重读《设计模式》一书的读书笔记第二篇,主要探讨工厂模式(Factory)
有几个重点
- 为什么需要工厂模式呢?工厂模式要解决的问题是创建对象实例的多变性,一个典型的例子就是假设我们的应用程序要既能够使用SQL Server作为数据库,也需要支持使用Oracle作为数据库(当然还可能会有其他的数据库),那么如何在不修改应用程序的情况下,能让它自动适用多种数据源呢?答案就是工厂模式。
- 工厂模式其实无处不在,而且即便我们自己以前没有写过,但至少都用到过了。在.NET框架中,很多地方都有工厂模式的影子。
- 工厂模式的核心是面向接口的编程。
- 工厂模式的另外一个核心是动态加载类型,也就是通过反射动态加载某个类型的实例。
- 工厂模式有两个具体的子模式
- 工厂方法模式(Factory Method) ——应用得更加多一些
- 抽象工厂模式(可以理解为更加复杂一些的场景)——Abastract Factory
下面有一个简单的实例(工厂方法模式:Factory Method)
using System;
using System.Collections.Generic;
using System.Reflection;
namespace DesignPatternSample_Factory
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("使用SQL Server的数据访问组件");
IDAL dal = Factory.GetDALInstance("DesignPatternSample_Factory.SQLServerDAL");
foreach (var item in dal.GetEmployee())
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.WriteLine("使用Oracle的数据访问组件");
dal = Factory.GetDALInstance("DesignPatternSample_Factory.OracleDAL");
foreach (var item in dal.GetEmployee())
{
Console.WriteLine(item);
}
Console.Read();
}
}
//第一步:定义接口
///
/// 定义一个数据访问层的接口,要求所有数据访问层都实现该接口
///
interface IDAL {
List<string> GetEmployee();
}
//第二步:定义工厂
class Factory
{
public static IDAL GetDALInstance(string typeName) {
return Assembly.GetExecutingAssembly().CreateInstance(typeName) as IDAL;
}
}
//第三步:具体实现DAL
class SQLServerDAL : IDAL
{
#region IDAL 成员
public List<string> GetEmployee()
{
return new List<string>(new[] { "John", "Mike" });
}
#endregion
}
class OracleDAL : IDAL
{
#region IDAL 成员
public List<string> GetEmployee()
{
return new List<string>(new[] { "Roy", "Rebecca" });
}
#endregion
}
}
下面再来看一个抽象工厂的模式实现的代码例子,从代码中可以看出,如果工厂需要做一系列的动态化工作,那么可以考虑抽象工厂模式。
using System;
using System.Configuration;
using System.Reflection;
namespace DesignPattern_Factory_AbstractFactorySample
{
class Program
{
static void Main(string[] args)
{
var factoryType = ConfigurationManager.AppSettings["FactoryType"];
var factory = Assembly.GetExecutingAssembly().CreateInstance(factoryType) as Factory;
var profile = factory.GetProfileDALInstance();
var business = factory.GetBusinessDALInstance();
profile.Load("Test");
profile.Save();
business.CreateOrder(1, DateTime.Now, 1);
}
}
#region 接口定义和抽象工厂定义
interface IProfileDAL {
void Save();
object Load(string key);
}
interface IBusinessDAL
{
int CreateOrder(int orderID, DateTime time, int employeeId);
}
abstract class Factory
{
public abstract IProfileDAL GetProfileDALInstance();
public abstract IBusinessDAL GetBusinessDALInstance();
}
#endregion
#region 一套简单的工厂及其实现
class SimpleFactory : Factory
{
public override IProfileDAL GetProfileDALInstance()
{
return new SimpleProfileDAL();
}
public override IBusinessDAL GetBusinessDALInstance()
{
return new SimpleBusinessDAL();
}
}
class SimpleProfileDAL : IProfileDAL
{
#region IProfileDAL 成员
public void Save()
{
}
public object Load(string key)
{
return this.GetType();
}
#endregion
}
class SimpleBusinessDAL : IBusinessDAL {
#region IBusinessDAL 成员
public int CreateOrder(int orderID, DateTime time, int employeeId)
{
return 0;
}
#endregion
}
#endregion
#region 一套复杂的工厂及其实现
class ComplexFactory : Factory {
public override IProfileDAL GetProfileDALInstance()
{
return new ComplexProfileDAL();
}
public override IBusinessDAL GetBusinessDALInstance()
{
return new ComplexBusinessDAL();
}
}
class ComplexProfileDAL : IProfileDAL
{
#region IProfileDAL 成员
public void Save()
{
throw new NotImplementedException();
}
public object Load(string key)
{
throw new NotImplementedException();
}
#endregion
}
class ComplexBusinessDAL : IBusinessDAL
{
#region IBusinessDAL 成员
public int CreateOrder(int orderID, DateTime time, int employeeId)
{
throw new NotImplementedException();
}
#endregion
}
#endregion
}