三.创建型设计模式——Simple Factory Pattern(简单工厂模式)

  • 定义

  专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。简单工厂(Simple Factory)模式又称为静态工厂方法(Static Factory Method)模式,属于类的创建型模式,通常它根据变量的不同返回不同的类的实例。UML类图如下:

  

  简单工厂模式的实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品类的实例。简单工厂模式实际上不属于23个GoF模式,但它可以作为GoF的工厂方法模式(Factory Method)的一个引导。从上图可以看出,简单工厂模式涉及到工厂角色、抽象产品角色和具体产品角色三个参与者。

  (1) 工厂(Creator)角色:是简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。

  (2) 抽象产品(Product)角色:是简单工厂模式所创建的所以对象的父类,它负责描述所有实例所共有的公共的接口。

  (3) 具体产品(Concrete Product)角色:是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

  典型应用的顺序图如下,单个工厂负责创建不同的产品。

  

  • 实例1——电子付款系统

  在电子付款系统中,会存在很多种电子交易方式,包括虚拟支票、信用卡、有线传送等。

  

  

代码
//抽象电子付款类
abstract class EFT
{
public abstract void process();
}
//具体子类,虚拟支票
class VirtualCheck : EFT
{
public override void process()
{
Console.WriteLine(
"虚拟支票处理中");
}
}
//具体子类,万事达卡
class MasterCard : EFT
{
public override void process()
{
Console.WriteLine(
"万事达卡处理中");
}
}
//简单工厂类
class EFTFactory
{
public EFT createEFT(string type)
{
switch (type.ToLower())
{
case "virtualcheck":
return new VirtualCheck();
case "mastercard":
return new MasterCard();
default:
return null;
}
}
}

//客户应用测试
class Client
{
[STAThread]
static void Main(string[] args)
{
EFT eft;
EFTFactory eftFactory
= new EFTFactory();
eft
= eftFactory.createEFT("VirtualCheck");
eft.process();
eft
= eftFactory.createEFT("MasterCard");
eft.process();
Console.Read();
}
}

 

 

  • 实例2——学校登陆系统

  系统允许多个级别的用户登陆系统,通过登录名及口令来区分不同的用户级别。学校负责人及教师派生出学校用户类SchoolUser,一个实例工厂SimpleFactory提供一个方法,用于根据登录名/口令来生成不同级别的类的实例。

  

 

代码
//基类
public class SchoolUser
{
public string FName;
public string LName;
public string UserType;
public void Show()
{
Console.WriteLine(
"First Name:" + FName + "\n");
Console.WriteLine(
"Last Name:" + LName + "\n");
Console.WriteLine(
"User Type:" + UserType + "\n");
}
}
//派生类,学校负责人
public class SchoolPrincipal : SchoolUser
{
public SchoolPrincipal()
{
FName
= "David";
LName
= "Smith";
UserType
= "Principal";
}
}
//派生类,学校老师
public class SchoolTeacher : SchoolUser
{
public SchoolTeacher()
{
FName
= "Patrecia";
LName
= "Terry";
UserType
= "Teacher";
}
}
//简单工厂类
public class SimpleFactory
{
public SchoolUser GetSchoolUser(string user, string password)
{
if (user == "Principal" && password == "Principal")
return new SchoolPrincipal();
else if (user == "Teacher" && password == "Teacher")
return new SchoolTeacher();
return null;
}
}

//客户应用测试
class Client
{
[STAThread]
static void Main(string[] args)
{
SimpleFactory sf
= new SimpleFactory();
SchoolUser su;
su
= sf.GetSchoolUser("Principal", "Principal");
Console.WriteLine(
"-------------------校长登陆-------------------");
su.Show();
su
= sf.GetSchoolUser("Teacher", "Teacher");
Console.WriteLine(
"-------------------教师登陆-------------------");
su.Show();
Console.Read();
}
}

 

 

  • 实例3——手机简单工厂

  手机简单工厂可以直接返回两种不同的手机,它可以生成MOTOROLA手机,也可以生成Nokia手机。

  

 

代码
//接口
public interface iMobile
{
void Call();
}
//具体产品
public class Nokia : iMobile
{
public void Call()
{
Console.WriteLine(
"一部Nokia手机生成了");
}
}
//具体产品
public class MOTOROLA : iMobile
{
public void Call()
{
Console.WriteLine(
"一部MOTOROLA手机生成了");
}
}
//简单工厂类MobileFactory通过传入参数来确定返回哪种手机的相关信息
public class MobileFactory
{
public iMobile GetMobile(string title)
{
if (title.ToLower() == "nokia")
return new Nokia();
else if (title.ToLower() == "motorola")
return new MOTOROLA();
return null;
}
}
//客户应用测试
class Client
{
[STAThread]
static void Main(string[] args)
{
MobileFactory mf
= new MobileFactory();
iMobile m;
m
= mf.GetMobile("Nokia");
m.Call();
m
= mf.GetMobile("MOTOROLA");
m.Call();
Console.Read();
}
}
  • 优势和缺陷

  在简单工厂模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面中摆脱出来,仅仅需要负责“消费”对象就可以了,而不必管这些对象究竟是如何创建以及如何组织的。这样就明确区分了各自的职责和权力,有利于整个软件体系结构的优化。

  不过,凡事有利就有弊,简单工厂模式的缺点也正体现在其工厂类上。由于工厂类集中了所有实例的创建逻辑,很容易违反GRASPR的高内聚的责任分配原则。将全部创建逻辑都集中到一个工厂类还有另外一个缺点,那就是当系统中的具体产品类不断增多时,可能会出现要求工厂类根据不同条件创建不同实例的需求。这种对条件的判断和对具体产品类的判断交错在一起,很难避免模块功能的蔓延,对系统的扩展和维护也非常不利。

  • 应用情景

  下列情况适于应用简单工厂模式:

  1. 工厂类负责创建的对象比较少。

  2. 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心。

  由于简单工厂很容易违反GRASP的高内聚责任分配原则,因此一般只在很简单的情况下应用。

posted on 2010-10-18 23:20  tLEE  阅读(839)  评论(0编辑  收藏  举报

导航