类比生活中的概 念,当我们需要打电话的时候,我们需要一部手机,我们通常会选择直接去卖手机的实体店买。但在程序设计中,当我们需要调用一个类(PhoneA或 PhoneB)的方法的时候,我们往往还要关心他是怎么new出来的(见代码段1)。这就好比我们自己还要去工厂里面告诉他们你要怎么生产出一部我需要的 手机。而我们只关心他能不能打电话,你怎么做的关我屁事。所以这就有了工厂模式。工厂模式其实就是抽象出一个工厂,我需要什么手机,去哪个工厂买就行了。 我不必关心他的制作过程,你只要能生产我要的功能的手机就行。所以我们需要引入简单工厂,让我们不用再关心手机怎么生产的,具体代码的实现见代码段2
public class Customer
{
public void CallSomeOne(){
PhoneA p1 = new PhoneA();
p1.Call();
}
}
public class PhoneA
{
public void Call(){}
}
public class PhoneB
{
public void Call(){}
}
{
public void CallSomeOne(){
PhoneA p1 = new PhoneA();
p1.Call();
}
}
public class PhoneA
{
public void Call(){}
}
public class PhoneB
{
public void Call(){}
}
代码段1 :通常的调用类方法的方式
using System;
namespace Example1
{
public interface IProduct { }
public class PhoneA : IProduct { }
public class PhoneB : IProduct { }
public class Factory
{
public IProduct Create()
{
// 工厂决定到底实例化哪个子类。
return new PhonetA ();
}
}
}
using System;
namespace Example1
{
public enum Category
{
A,
}
public static class ProductFactory
{
public static IProduct Create(Category category)
{
switch (category)
{
case Category.A:
return new PhoneA();
case Category.B:
return new PhoneB();
default:
throw new NotSupportedException();
}
}
}
}
namespace Example1
{
public interface IProduct { }
public class PhoneA : IProduct { }
public class PhoneB : IProduct { }
public class Factory
{
public IProduct Create()
{
// 工厂决定到底实例化哪个子类。
return new PhonetA ();
}
}
}
using System;
namespace Example1
{
public enum Category
{
A,
}
public static class ProductFactory
{
public static IProduct Create(Category category)
{
switch (category)
{
case Category.A:
return new PhoneA();
case Category.B:
return new PhoneB();
default:
throw new NotSupportedException();
}
}
}
}
代码段2:简单工厂模式的实现
[TestMethod]
public void Test()
{
Factory factory = new Factory();
IProduct phone = factory.Create();
Assert.AreEqual<Type>(phone.GetType(), typeof(PhoneA));
}
public void Test()
{
Factory factory = new Factory();
IProduct phone = factory.Create();
Assert.AreEqual<Type>(phone.GetType(), typeof(PhoneA));
}
代码段3:对简单工厂模式的测试
新的问题
其 实刚刚也提到了,我们只要一只能打电话的手机,我就想去实体店买一下,我才不关心是哪个工厂生产的呢~而在简单工厂中,我们还需要关心是哪个工厂生产的 (见代码段3)。所以我们在代码里面实现一个实体店,这样我们就不用关心到底是哪个工厂生产的啦。所以我们需要引入抽象工厂,这样我们只需要跟实体店打交 道,不要再关心要去找什么工厂拿手机了。具体的实现见代码段4.我们可以利用配置文件实现对工厂的选择,对产品的选择,因为本文不想引入其他的概念,这里 就不讨论了。
namespace Example2
{
/// <summary>
/// 抽象的工厂类型特性描述
/// </summary>
public interface IFactory
{
IProduct Create(); // 每个工厂所需要具有的工厂方法——创建产品
}
/// <summary>
/// 实体工厂类型
/// </summary>
public class FactoryA : IFactory
{
public IProduct Create()
{
return new PhoneA();
}
}
/// <summary>
/// 实体工厂类型
/// </summary>
public class FactoryB : IFactory
{
public IProduct Create()
{
return new PhoneB();
}
}
}
using System;
using System.Diagnostics;
namespace Example2
{
class Client
{
public void SomeMethod()
{
IFactory factory = new FactoryA(); // 获得了抽象Factory的同时,与FactoryA产生依赖;
IProduct Phone = factory.Create(); // 后续操作仅以来抽象的IFactory和IProduct完成
// ...
}
private IFactory factory;
public Client(IFactory factory) // 将IFactory通过Setter方式注入
{
if (factory == null) throw new ArgumentNullException("factory");
this.factory = factory;
}
public void AnotherMethod()
{
IProduct Phone = factory.Create();
// ... ...
}
}
}
{
/// <summary>
/// 抽象的工厂类型特性描述
/// </summary>
public interface IFactory
{
IProduct Create(); // 每个工厂所需要具有的工厂方法——创建产品
}
/// <summary>
/// 实体工厂类型
/// </summary>
public class FactoryA : IFactory
{
public IProduct Create()
{
return new PhoneA();
}
}
/// <summary>
/// 实体工厂类型
/// </summary>
public class FactoryB : IFactory
{
public IProduct Create()
{
return new PhoneB();
}
}
}
using System;
using System.Diagnostics;
namespace Example2
{
class Client
{
public void SomeMethod()
{
IFactory factory = new FactoryA(); // 获得了抽象Factory的同时,与FactoryA产生依赖;
IProduct Phone = factory.Create(); // 后续操作仅以来抽象的IFactory和IProduct完成
// ...
}
private IFactory factory;
public Client(IFactory factory) // 将IFactory通过Setter方式注入
{
if (factory == null) throw new ArgumentNullException("factory");
this.factory = factory;
}
public void AnotherMethod()
{
IProduct Phone = factory.Create();
// ... ...
}
}
}
总结:
1、工厂方法模式注重的是整体对象的创建方法
2、工厂方法的意图非常明确,它把类的实例化过程延迟到子类,将new()的工作交给工厂 完成。同时,增加一个抽象的工厂定义,解决一系列具有统一通用工厂方法的实体工厂问题。 在.NET 平台中,我们可以借助配置、泛型和委托的方法在实现经典模式目的的同时,获得工厂类型与客户程序间更加松散的构造过程。
更多内容,请参考:http://www.jbxue.com/wb/aspnet