工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类。工厂模式有以下几种形态:
· 简单工厂(Simple Factory)模式
· 工厂方法(Factory Method)模式
· 抽象工厂(Abstract Factory)模式
Simple Factory模式根据提供给它的数据,返回几个可能类中的一个类的实例。通常它返回的类都有一个公共的父类和公共的方法。
Simple Factory模式实际上不是GoF 23个设计模式中的一员。
下面我们来看看一个Simple Factory的例子:
以上为整个类结构的UML图。
工厂类角色Creator (PersonSimFactory):工厂类在客户端的直接控制下(GetPerson方法)创建产品对象。
抽象产品角色Product (Person):定义简单工厂创建的对象的父类或它们共同拥有的接口。可以是一个类、抽象类或接口(我们这里使用了类为例)当然你也可以把下面的Person类改为abstract类,把GetInfo()变为abstract函数来运行或者可以将Person变为Interface,将实现延迟到子类中也没有问题。
具体产品角色CreatedProduct (WritePerson, YellowPerson,BlackPerson):定义工厂具体加工出的对象。
具体代码(C#):
namespace SimFactory
{
/// <summary>
///============== Program Description==============
///Name:SimFactory.cs
///Objective:SimFactory
///Date:2006-02-09
///Written By coffee.liu
///================================================
/// </summary>
public class Person
{
protected string sex,race;
public string GetSex(){
return sex;
}
public string GetRace(){
return race;
}
public virtual void GetInfo(){
}
}
public class YellowPerson:Person
{
public YellowPerson()
{
sex="Man";
race="Yellow";
}
public YellowPerson(string Ysex)
{
sex=Ysex;
race="Yellow";
}
public override void GetInfo(){
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
public class BlackPerson:Person
{
public BlackPerson()
{
sex="Man";
race="Black";
}
public BlackPerson(string Bsex)
{
sex=Bsex;
race="Black";
}
public override void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
public class WritePerson:Person
{
public WritePerson()
{
sex="Man";
race="Write";
}
public WritePerson(string Wsex)
{
sex=Wsex;
race="Write";
}
public override void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
public class PersonSimFactory{
public PersonSimFactory(){}
public Person GetPerson(string RaceType){
if (RaceType=="Yellow")
return new YellowPerson();
else
if (RaceType=="Black")
return new BlackPerson();
else
if (RaceType=="Write")
return new WritePerson();
else
return new YellowPerson();
}
}
}
////////
///////
///////
using System;
namespace SimFactory
{
/// <summary>
///============== Program Description==============
///Name:SimFactory.cs
///Objective:SimFactory
///Date:2006-02-09
///Written By coffee.liu
///================================================
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
PersonSimFactory PSF=new PersonSimFactory();
Person PP=PSF.GetPerson("Yellow");
PP.GetInfo();
Console.WriteLine(".");
PP=PSF.GetPerson("Black");
PP.GetInfo();
Console.WriteLine(".");
PP=PSF.GetPerson("Write");
PP.GetInfo();
}
}
}
具体代码(Pascal):
//============== Program Description==============
//Name:SimFactory.dpr
//Objective:SimFactory
//Date:2006-04-23
//Written By coffee.liu
//================================================
{$APPTYPE CONSOLE}
uses
SysUtils;
type Person=class
protected
sex:string;
race:string;
public function GetSex():string;
public function GetRace():string;
public procedure GetInfo;virtual;abstract;
end;
type YellowPerson=class(Person)
constructor YellowPerson();
public procedure GetInfo;override;
end;
type BlackPerson=class(Person)
constructor BlackPerson();
public procedure GetInfo;override;
end;
type WritePerson=class(Person)
constructor WritePerson();
public procedure GetInfo;override;
end;
type PersonSimFactory=class
constructor PersonSimFactory();
public function GetPerson(RaceType:string):Person;
end;
{ Person }
function Person.GetRace: string;
begin
result:=race;
end;
function Person.GetSex: string;
begin
result:=sex;
end;
{ YellowPerson }
constructor YellowPerson.YellowPerson;
begin
sex:='Man';
race:='Yellow';
end;
procedure YellowPerson.GetInfo;
begin
inherited;
WriteLn('the '+race+' Person Info:'+sex);
end;
{ WritePerson }
procedure WritePerson.GetInfo;
begin
inherited;
WriteLn('the '+race+' Person Info:'+sex);
end;
constructor WritePerson.WritePerson;
begin
sex:='Man';
race:='Write';
end;
{ BlackPerson }
constructor BlackPerson.BlackPerson;
begin
sex:='Man';
race:='Black';
end;
procedure BlackPerson.GetInfo;
begin
inherited;
WriteLn('the '+race+' Person Info:'+sex);
end;
{ PersonSimFactory }
function PersonSimFactory.GetPerson(RaceType: string): Person;
begin
if RaceType='Yellow' then
result:=YellowPerson.YellowPerson
else
if RaceType='Black' then
result:=BlackPerson.BlackPerson
else
if RaceType='Write' then
result:=WritePerson.WritePerson
else
result:=YellowPerson.YellowPerson;
end;
constructor PersonSimFactory.PersonSimFactory;
begin
inherited;
end;
var
PSF:PersonSimFactory;
PP:Person;
begin
PSF:=PersonSimFactory.PersonSimFactory;
PP:=PSF.GetPerson('Yellow');
PP.GetInfo;
WriteLn('..');
PP:=PSF.GetPerson('Black');
PP.GetInfo;
WriteLn('..');
PP:=PSF.GetPerson('Write');
PP.GetInfo;
WriteLn('..error.');
PP:=PSF.GetPerson('Write11');
PP.GetInfo;
end.
我们甚至可以将抽象产品类作为子类的工厂:
程序代码(C#):
namespace SimFactoryPlus1
{
/// <summary>
///============== Program Description==============
///Name:SimFactory.cs
///Objective:SimFactory
///Date:2006-02-09
///Written By coffee.liu
///================================================
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
Person PP=Person.GetPerson("Yellow");
PP.GetInfo();
Console.WriteLine(".");
PP=Person.GetPerson("Black");
PP.GetInfo();
Console.WriteLine(".");
PP=Person.GetPerson("Write");
PP.GetInfo();
}
}
public class Person
{
protected string sex,race;
public string GetSex()
{
return sex;
}
public string GetRace()
{
return race;
}
public virtual void GetInfo()
{
}
public static Person GetPerson(string RaceType)
{
if (RaceType=="Yellow")
return new YellowPerson();
else
if (RaceType=="Black")
return new BlackPerson();
else
if (RaceType=="Write")
return new WritePerson();
else
return new YellowPerson();
}
}
public class YellowPerson:Person
{
public YellowPerson()
{
sex="Man";
race="Yellow";
}
public YellowPerson(string Ysex)
{
sex=Ysex;
race="Yellow";
}
public override void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
public class BlackPerson:Person
{
public BlackPerson()
{
sex="Man";
race="Black";
}
public BlackPerson(string Bsex)
{
sex=Bsex;
race="Black";
}
public override void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
public class WritePerson:Person
{
public WritePerson()
{
sex="Man";
race="Write";
}
public WritePerson(string Wsex)
{
sex=Wsex;
race="Write";
}
public override void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
}
程序代码(Pascal)
//============== Program Description==============
//Name:SimFactory.dpr
//Objective:SimFactory
//Date:2006-04-23
//Written By coffee.liu
//================================================
{$APPTYPE CONSOLE}
uses
SysUtils;
type Person=class
protected
sex:string;
race:string;
public function GetSex():string;
public function GetRace():string;
public procedure GetInfo;virtual;abstract;
class function GetPerson(RaceType:string):Person;
end;
type YellowPerson=class(Person)
constructor YellowPerson();
public procedure GetInfo;override;
end;
type BlackPerson=class(Person)
constructor BlackPerson();
public procedure GetInfo;override;
end;
type WritePerson=class(Person)
constructor WritePerson();
public procedure GetInfo;override;
end;
{ Person }
class function Person.GetPerson(RaceType: string): Person;
begin
if RaceType='Yellow' then
result:=YellowPerson.YellowPerson
else
if RaceType='Black' then
result:=BlackPerson.BlackPerson
else
if RaceType='Write' then
result:=WritePerson.WritePerson
else
result:=YellowPerson.YellowPerson;
end;
function Person.GetRace: string;
begin
result:=race;
end;
function Person.GetSex: string;
begin
result:=sex;
end;
{ YellowPerson }
constructor YellowPerson.YellowPerson;
begin
sex:='Man';
race:='Yellow';
end;
procedure YellowPerson.GetInfo;
begin
inherited;
WriteLn('the '+race+' Person Info:'+sex);
end;
{ WritePerson }
procedure WritePerson.GetInfo;
begin
inherited;
WriteLn('the '+race+' Person Info:'+sex);
end;
constructor WritePerson.WritePerson;
begin
sex:='Man';
race:='Write';
end;
{ BlackPerson }
constructor BlackPerson.BlackPerson;
begin
sex:='Man';
race:='Black';
end;
procedure BlackPerson.GetInfo;
begin
inherited;
WriteLn('the '+race+' Person Info:'+sex);
end;
var
PP:Person;
begin
PP:=Person.GetPerson('Yellow');
PP.GetInfo;
WriteLn('..');
PP:=Person.GetPerson('Black');
PP.GetInfo;
WriteLn('..');
PP:=Person.GetPerson('Write');
PP.GetInfo;
WriteLn('..error.');
PP:=Person.GetPerson('Write11');
PP.GetInfo;
end.
我们甚至可以将3种角色全部合并!
程序代码(C#):
namespace SimFactoryPlus2
{
/// <summary>
///============== Program Description==============
///Name:SimFactory.cs
///Objective:SimFactory
///Date:2006-02-09
///Written By coffee.liu
///================================================
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
Person PP=Person.GetPerson("Yellow");
PP.GetInfo();
Console.WriteLine(".");
PP=Person.GetPerson("Black");
PP.GetInfo();
Console.WriteLine(".");
PP=Person.GetPerson("Write");
PP.GetInfo();
}
}
public class Person
{
private class YellowPerson:Person
{
public YellowPerson()
{
sex="Man";
race="Yellow";
}
public YellowPerson(string Ysex)
{
sex=Ysex;
race="Yellow";
}
public override void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
private class BlackPerson:Person
{
public BlackPerson()
{
sex="Man";
race="Black";
}
public BlackPerson(string Bsex)
{
sex=Bsex;
race="Black";
}
public override void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
private class WritePerson:Person
{
public WritePerson()
{
sex="Man";
race="Write";
}
public WritePerson(string Wsex)
{
sex=Wsex;
race="Write";
}
public override void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
}
protected string sex,race;
public string GetSex()
{
return sex;
}
public string GetRace()
{
return race;
}
public virtual void GetInfo()
{
}
public static Person GetPerson(string RaceType)
{
if (RaceType=="Yellow")
return new YellowPerson();
else
if (RaceType=="Black")
return new BlackPerson();
else
if (RaceType=="Write")
return new WritePerson();
else
return new YellowPerson();
}
}
}
程序代码(Pascal)
//============== Program Description==============
//Name:SimFactory.dpr
//Objective:SimFactory
//Date:2006-04-23
//Written By coffee.liu
//================================================
{$APPTYPE CONSOLE}
uses
SysUtils;
type Person=class
protected
sex:string;
race:string;
constructor Create(Se:string;Ra:String);
public function GetSex():string;
public function GetRace():string;
public procedure GetInfo;
class function GetPerson(RaceType:string):Person;
end;
{ Person }
constructor Person.Create(Se:string;Ra:String);
begin
inherited create;
sex:=Se;
race:=Ra;
end;
procedure Person.GetInfo;
begin
WriteLn('the '+race+' Person Info:'+sex);
end;
class function Person.GetPerson(RaceType: string): Person;
begin
if RaceType='Yellow' then
result:=person.Create('Man','Yellow')
else
if RaceType='Black' then
result:=person.Create('Man','Black')
else
if RaceType='Write' then
result:=person.Create('Man','Write')
else
result:=person.Create('Man','Yellow');
end;
function Person.GetRace: string;
begin
result:=race;
end;
function Person.GetSex: string;
begin
result:=sex;
end;
var
PP:Person;
begin
PP:=Person.GetPerson('Yellow');
PP.GetInfo;
WriteLn('..');
PP:=Person.GetPerson('Black');
PP.GetInfo;
WriteLn('..');
PP:=Person.GetPerson('Write');
PP.GetInfo;
WriteLn('..error.');
PP:=Person.GetPerson('Write11');
PP.GetInfo;
end.
注意上面Pascal代码由于功能上的限制其实已经退化。
小结:
简单工厂能返回具有相同方法的类的实例,他们可以是不同的派生子类的实例,也可以是实际上毫无关系仅仅是共享了相同借口的类。不管哪种形式,这些实例中的方法必须是相同的,并且能够交替使用。