Simple Factory Pattern (简单工厂模式)
特性:
- 把类的实例化工作,集中到一个「工厂类」去处理,亦即将 new instance 的工作,都交给一个「工厂」去处理,而不要分散写在各个类中。
- 客户端程序,与创建实例 (对象) 的工作必须隔离,亦即「解耦」,客户端程序只要专注于自己的业务逻辑。适用于客户端程序在开发过程中,尚无法预知要创建的具体类型。
- 产品具体的实现能和客户端隔离,便于事后抽换。
Simple Factory Pattern (简单工厂模式)、Factory Method Pattern (工厂方法模式),在实作的代码中,有时很难明确去界定此二者。Simple Factory 的特性,如前所述,在于将创建实例 (new instance) 的工作,集中由特定的一个「工厂类」来处理,避免写在各个类中,以方便日后添加新功能,和修改既有的功能。
如下「进口水果」的代码,为 O'Reilly 的「C# 3.0 Design Patterns」这本书籍 [1] 第五章的 Factory Method 示例。乍看之下,我觉得它比较像 Simple Factory Pattern,因其仍将创建实例,和部分逻辑判断的工作,都集中在一个 工厂类 (Creator1 类) 去处理,导致日后要添加新功能 (多引进一个国家的水果),或要修改判断「进口月份」的逻辑时,仍要修改 server-side 的这个「工厂类」,而无法只修改 client-side 的 Page_Load 方法,违背了「开放-封闭」原则。
但这个示例,要实例化哪个类型,是由「工厂类」以及客户端 (水果店主人) 的 Page_Load 方法,共同决定的。透过 IProduct 接口,看似隔离了客户端程序、具体 Product 的依赖关系,但客户端程序仍有创建对象的决定权,因此其与创建实例 (对象) 的工作并未真正隔离。
SimpleFactory.ASPx.cs
using System;
//这个示例事实上算是一个 Factory Method Pattern
public partial class SimpleFactory : System.Web.UI.Page
{
//客户端调用(Client-Side)。这个示例的客户端,如同一间水果店的店主人。
protected void Page_Load(object sender, EventArgs e)
{
Creator1 c = new Creator1(); //工厂类實體
IProduct product;
//由客户端决定要具体实例化哪些类型。
//但此示例的特点,为客户端不需要知道产品类型。
for (int i = 1; i <= 12; i++)
{
//客户端不需要知道产品类型。把创建哪种具体产品的决定,委托给了工厂方法
product = c.factoryMethod(i);
Response.Write("水果进口, " + i + "月: " + product.shipFrom() + "
");
}
}
//这个示例,要实例化哪个类型,是由「工厂类」以及 Client-Side 的 Page_Load() 方法,共同决定的。
//透过 IProduct 接口,看似隔离了客户端程序、具体 Product 的依赖关系,
//但客户端程序仍有创建对象的决定权,因此其与创建实体 (对象) 的工作并未真正隔离。
//即使日后修改了某个子类 shipFrom() 里的实作方式,对客户端不会有影响,
//客户端只要知道如何操作 shipFrom() 去进口水果即可。
}
//所有的产品,必须实现这个接口。如此一来,先建立一种「契约」,
//以后要增添、修改产品时,就可由这个接口(或抽象类)来操作。
interface IProduct
{
//隐藏实现细节。
//事前不知道要创建哪种类的实体(产品),延至 Creator1 类或「客户端」中实现。
string shipFrom();
}
//单一职责原则,每一个类都只负责一件具体的事情。
// 台湾的水果供货商。
class ProductA : IProduct
{
public string shipFrom()
{
return " from 台湾";
}
}
//单一职责原则,每一个类都只负责一件具体的事情。
// 美国的水果供货商。
class ProductB : IProduct
{
public string shipFrom()
{
return "from 美国";
}
}
//单一职责原则,每一个类都只负责一件具体的事情
class DefaultProduct : IProduct
{
public string shipFrom()
{
return "不进口";
}
}
//工厂类 (水果采购人员),负责创建实体(采购水果)。只有这个类,知道如何创建这些产品的逻辑
class Creator1
{
//日后若引进新产品 (多引进一个国家的水果)、修改旧产品,可集中在这里抽换;
//但缺点亦如是,亦即仍需修改这里的 Server-Side 代码,必须修改此一工厂类。
//此处做法,偏向「简单工厂模式」的实体创建。
public IProduct factoryMethod(int month)
{
if (month >= 4 && month <= 11)
return new ProductA();
else
if (month == 1 || month == 2 || month == 12)
return new ProductB();
else
return new DefaultProduct();
}
}
//另一个工厂类
//class Creator2
//{
// public IProduct factoryMethod(int month, int day)
// {
// 不同的水果进口方式
// }
//}
/*
执行结果:
水果进口, 1月: from 美国
水果进口, 2月: from 美国
水果进口, 3月: 不进口
水果进口, 4月: from 台湾
水果进口, 5月: from 台湾
水果进口, 6月: from 台湾
水果进口, 7月: from 台湾
水果进口, 8月: from 台湾
水果进口, 9月: from 台湾
水果进口, 10月: from 台湾
水果进口, 11月: from 台湾
水果进口, 12月: from 美国
*/
//
NET技术:C# Design Patterns (1) - Factory Method,转载需保留来源!
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。