二、工厂方法模式(Factory Method Pattern)
2008-03-13 00:36
190 查看
不是用一个专门的类来决定实例化哪一个子类,而是超类把这种决定延迟到每个子类.按这种模式编写的程序定义了一个抽象类,它去创建对象,但让子类决定创建哪一种对象.
例子: 在游泳比赛中为运动员确定泳道.最快的三名选手安排在最快的三组里的中央泳道上,第二快的三名选手安排在头三组的紧邻的泳道上,依次类推.
抽象类Event与其派生类:
public abstract class Event ...{ //抽象类:Event
protected int numLanes;
protected ArrayList swimmers;
public Event(string filename, int lanes) ...{
numLanes = lanes;
swimmers = new ArrayList();
//读取游泳者信息数据
csFile f = new csFile(filename);
f.OpenForRead ();
string s = f.readLine();
while (s != null) ...{
Swimmer sw = new Swimmer(s);
swimmers.Add (sw);
s = f.readLine();
}
f.close();
}
public abstract Seeding getSeeding();
public abstract bool isPrelim();
public abstract bool isFinal();
public abstract bool isTimedFinal();
}
public class PrelimEvent:Event ...{ //Event的派生类PrelimEvent
public PrelimEvent(string filename, int lanes):base(filename,lanes) ...{
}
//return circle seeding
public override Seeding getSeeding() ...{
return new CircleSeeding(swimmers, numLanes);
//返回CircleSeeding的一个实例
}
public override bool isPrelim() ...{
return true;
}
public override bool isFinal() ...{
return false;
}
public override bool isTimedFinal() ...{
return false;
}
}
public class TimedFinalEvent:Event ...{ //Event的派生类TimedFinalEvent
public TimedFinalEvent(string filename, int lanes):base(filename, lanes) ...{
}
//return StraightSeeding class
public override Seeding getSeeding() ...{
return new StraightSeeding(swimmers, numLanes);
//返回StraightSeeding的一个实例
}
public override bool isPrelim() ...{
return false;
}
public override bool isFinal() ...{
return false;
}
public override bool isTimedFinal() ...{
return true;
}
}
抽象类:Seeding与其派生类
public abstract class Seeding ...{ //抽象类:Seeding
protected int numLanes;
protected int[] lanes;
public abstract IEnumerator getSwimmers();
public abstract int getCount();
public abstract int getHeats();
protected abstract void seed();
//--------------------------------
protected void calcLaneOrder() ...{
lanes = new int[numLanes];
int mid = numLanes / 2;
if (odd(numLanes))
mid = mid + 1; //start in middle lane
int incr = 1;
int ln = mid;
//create array of lanes from
//center to outside
for (int i=0; i< numLanes; i++) ...{
lanes[i] = ln;
ln = mid + incr;
incr = - incr;
if (incr > 0)
incr=incr+1;
}
}
//--------------------------------
private bool odd(int x) ...{
return(((x / 2)*2) != x);
}
}
//直接排位
public class StraightSeeding :Seeding ...{ //Seeding的派生类StraightSeeding
protected ArrayList swimmers;
protected Swimmer[] swmrs;
protected int count;
protected int numHeats;
public StraightSeeding(ArrayList sw, int lanes) ...{
swimmers = sw;
numLanes = lanes;
count = sw.Count;
calcLaneOrder();
seed();
}
//--------------------------------
protected override void seed() ...{
//loads the swmrs array and sorts it
sortUpwards();
int lastHeat = count % numLanes;
if (lastHeat < 3)
lastHeat = 3; //last heat must have 3 or more
int lastLanes = count - lastHeat;
numHeats = count / numLanes;
if (lastLanes > 0)
numHeats++;
int heats = numHeats;
//place heat and lane in each swimmer's object
int j = 0;
for (int i = 0; i < lastLanes; i++) ...{
Swimmer sw = swmrs[i];
sw.setLane(lanes[j++]);
sw.setHeat(heats);
if (j >= numLanes) ...{
heats--;
j=0;
}
}
//Add in last partial heat
if (j < numLanes)
heats--;
j = 0;
for (int i = lastLanes-1; i<count; i++) ...{
Swimmer sw = swmrs[i];
sw.setLane(lanes[j++]);
sw.setHeat(heats);
}
//copy from array back into ArrayList
swimmers = new ArrayList();
for (int i=0; i< count; i++)
swimmers.Add(swmrs[i]);
}
//--------------------------------
protected void sortUpwards() ...{
swmrs = new Swimmer[count];
for (int i=0; i < count; i++)
swmrs[i] = (Swimmer)swimmers[i];
for ( int i=0; i < count; i++) ...{
for (int j = i; j < count; j++) ...{
if (swmrs[i].getTime() > swmrs[j].getTime()) ...{
Swimmer swtemp = swmrs[i];
swmrs[i] = swmrs[j];
swmrs[j] = swtemp;
}
}
}
}
//--------------------------------
public override int getCount() ...{
return swimmers.Count ;
}
public override IEnumerator getSwimmers() ...{
return swimmers.GetEnumerator ();
}
//----------------------------------
public override int getHeats() ...{
return numHeats;
}
}
//循环排位
public class CircleSeeding:StraightSeeding //StraightSeeding的派生类CircleSeeding
...{
public CircleSeeding(ArrayList sw, int lanes):base(sw,lanes) ...{
seed();
}
//----------------------------
protected override void seed() ...{
int circle;
base.seed(); //do straight seed as default
if (numHeats >= 2 ) ...{
if (numHeats >= 3)
circle = 3;
else
circle = 2;
int i = 0;
for (int j = 0; j < numLanes; j++) ...{
for (int k = 0; k < circle; k++) ...{
swmrs[i].setLane(lanes[j]);
swmrs[i++].setHeat(numHeats - k);
}
}
}
}游泳者类Swimmer与使用到的其它类:
public class Swimmer //游泳者类
...{
private string firstName, lastName;
private int age;
private string club;
private float time;
private int heat, lane;
//--------------------------------------
public Swimmer(String dataline) ...{
StringTokenizer st = new StringTokenizer(dataline, " ");
string lineNumber = st.nextToken(); //ignore and discard
firstName = st.nextToken();
lastName = st.nextToken();
age = Convert.ToInt32 (st.nextToken().Trim());
club = st.nextToken().Trim();
string stime = st.nextToken().Trim();
int i = stime.IndexOf(":");
if (i > 0) ...{
stime = stime.Substring(0, i) + stime.Substring (i+1);
}
time = Convert.ToSingle ( stime);
}
//-------------------------------
public void setLane(int ln) ...{
lane = ln;
}
//-------------------------------
public int getLane() ...{
return lane;
}
//-------------------------------
public void setHeat(int ht) ...{
heat = ht;
}
//-------------------------------
public int getHeat() ...{
return heat;
}
//-------------------------------
public int getAge() ...{
return age;
}
//-------------------------------
public float getTime() ...{
return time;
}
//-------------------------------
public string getName() ...{
return firstName+" "+lastName;
}
//-------------------------------
public string getClub() ...{
return club;
}
}
/**//// <summary>
/// A simple file handlng class
/// </summary>
public class csFile
...{
private string fileName;
StreamReader ts;
StreamWriter ws;
private bool opened, writeOpened;
//-----------
public csFile() ...{
init();
}
//-----------
private void init() ...{
opened = false;
writeOpened = false;
}
//-----------
public csFile(string file_name) ...{
fileName = file_name;
init();
}
//-----------
public bool OpenForRead(string file_name)...{
fileName = file_name;
try ...{
ts = new StreamReader (fileName);
opened=true;
}
catch(FileNotFoundException e) ...{
return false;
}
return true;
}
//-----------
public bool OpenForRead() ...{
return OpenForRead(fileName);
}
//-----------
public string readLine() ...{
return ts.ReadLine ();
}
//-----------
public void writeLine(string s) ...{
ws.WriteLine (s);
}
//-----------
public void close() ...{
if (opened)
ts.Close ();
if(writeOpened)
ws.Close();
}
//-----------
public bool OpenForWrite() ...{
return OpenForWrite(fileName);
}
//-----------
public bool OpenForWrite(string file_name) ...{
try...{
ws = new StreamWriter (file_name);
fileName = file_name;
writeOpened = true;
return true;
}
catch(FileNotFoundException e) ...{
return false;
}
}
}
public class StringTokenizer ...{
private string data, delimiter;
private string[] tokens;
private int index;
public StringTokenizer(string dataLine) ...{
init(dataLine, " ");
}
private void init(String dataLine, string delim) ...{
delimiter = delim;
data = dataLine;
tokens = data.Split (delimiter.ToCharArray() );
index = 0;
}
public StringTokenizer(string dataLine, string delim) ...{
init(dataLine, delim);
}
public bool hasMoreElements() ...{
return (index < (tokens.Length));
}
public string nextToken() ...{
return nextElement();
}
public string nextElement() ...{
string s = tokens[index++];
while((s.Length <=0) && (index<tokens.Length ))
s = tokens[index++];
return s;
}
}
调用:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Seeding
...{
/**//// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
...{
private System.Windows.Forms.ListBox lsEvents;
private System.Windows.Forms.ListBox lsSwimmers;
/**//// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private ArrayList events;
private void init() ...{
//create array of events
events = new ArrayList ();
lsEvents.Items.Add ("500 Free");
lsEvents.Items.Add ("100 Free");
//and read in their data
events.Add (new TimedFinalEvent ("500free.txt", 6));
events.Add (new PrelimEvent ("100free.txt", 6));
}
public Form1()
...{
//
// Required for Windows Form Designer support
//
InitializeComponent();
init();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/**//// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
...{
if( disposing )
...{
if (components != null)
...{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form Designer generated code#region Windows Form Designer generated code
/**//// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
...{
this.lsEvents = new System.Windows.Forms.ListBox();
this.lsSwimmers = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// lsEvents
//
this.lsEvents.Location = new System.Drawing.Point(8, 24);
this.lsEvents.Name = "lsEvents";
this.lsEvents.Size = new System.Drawing.Size(112, 69);
this.lsEvents.TabIndex = 0;
this.lsEvents.SelectedIndexChanged += new System.EventHandler(this.lsEvents_SelectedIndexChanged);
//
// lsSwimmers
//
this.lsSwimmers.Location = new System.Drawing.Point(144, 24);
this.lsSwimmers.Name = "lsSwimmers";
this.lsSwimmers.Size = new System.Drawing.Size(192, 160);
this.lsSwimmers.TabIndex = 1;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(384, 205);
this.Controls.AddRange(new System.Windows.Forms.Control[] ...{
this.lsSwimmers,
this.lsEvents});
this.Name = "Form1";
this.Text = "Seeding Factory";
this.ResumeLayout(false);
}
#endregion
/**//// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
...{
Application.Run(new Form1());
}
private void lsEvents_SelectedIndexChanged(object sender, System.EventArgs e) ...{
int index = lsEvents.SelectedIndex ;
Event ev = (Event)events[index];
Seeding sd = ev.getSeeding();
IEnumerator en = sd.getSwimmers();
lsSwimmers.Items.Clear() ;
while(en.MoveNext ()) ...{
Swimmer sw = (Swimmer)en.Current ;
lsSwimmers.Items.Add(sw.getHeat()+" "+sw.getLane()+" "+sw.getName()+" "+sw.getTime());
}
}
}
}
例子: 在游泳比赛中为运动员确定泳道.最快的三名选手安排在最快的三组里的中央泳道上,第二快的三名选手安排在头三组的紧邻的泳道上,依次类推.
抽象类Event与其派生类:
public abstract class Event ...{ //抽象类:Event
protected int numLanes;
protected ArrayList swimmers;
public Event(string filename, int lanes) ...{
numLanes = lanes;
swimmers = new ArrayList();
//读取游泳者信息数据
csFile f = new csFile(filename);
f.OpenForRead ();
string s = f.readLine();
while (s != null) ...{
Swimmer sw = new Swimmer(s);
swimmers.Add (sw);
s = f.readLine();
}
f.close();
}
public abstract Seeding getSeeding();
public abstract bool isPrelim();
public abstract bool isFinal();
public abstract bool isTimedFinal();
}
public class PrelimEvent:Event ...{ //Event的派生类PrelimEvent
public PrelimEvent(string filename, int lanes):base(filename,lanes) ...{
}
//return circle seeding
public override Seeding getSeeding() ...{
return new CircleSeeding(swimmers, numLanes);
//返回CircleSeeding的一个实例
}
public override bool isPrelim() ...{
return true;
}
public override bool isFinal() ...{
return false;
}
public override bool isTimedFinal() ...{
return false;
}
}
public class TimedFinalEvent:Event ...{ //Event的派生类TimedFinalEvent
public TimedFinalEvent(string filename, int lanes):base(filename, lanes) ...{
}
//return StraightSeeding class
public override Seeding getSeeding() ...{
return new StraightSeeding(swimmers, numLanes);
//返回StraightSeeding的一个实例
}
public override bool isPrelim() ...{
return false;
}
public override bool isFinal() ...{
return false;
}
public override bool isTimedFinal() ...{
return true;
}
}
抽象类:Seeding与其派生类
public abstract class Seeding ...{ //抽象类:Seeding
protected int numLanes;
protected int[] lanes;
public abstract IEnumerator getSwimmers();
public abstract int getCount();
public abstract int getHeats();
protected abstract void seed();
//--------------------------------
protected void calcLaneOrder() ...{
lanes = new int[numLanes];
int mid = numLanes / 2;
if (odd(numLanes))
mid = mid + 1; //start in middle lane
int incr = 1;
int ln = mid;
//create array of lanes from
//center to outside
for (int i=0; i< numLanes; i++) ...{
lanes[i] = ln;
ln = mid + incr;
incr = - incr;
if (incr > 0)
incr=incr+1;
}
}
//--------------------------------
private bool odd(int x) ...{
return(((x / 2)*2) != x);
}
}
//直接排位
public class StraightSeeding :Seeding ...{ //Seeding的派生类StraightSeeding
protected ArrayList swimmers;
protected Swimmer[] swmrs;
protected int count;
protected int numHeats;
public StraightSeeding(ArrayList sw, int lanes) ...{
swimmers = sw;
numLanes = lanes;
count = sw.Count;
calcLaneOrder();
seed();
}
//--------------------------------
protected override void seed() ...{
//loads the swmrs array and sorts it
sortUpwards();
int lastHeat = count % numLanes;
if (lastHeat < 3)
lastHeat = 3; //last heat must have 3 or more
int lastLanes = count - lastHeat;
numHeats = count / numLanes;
if (lastLanes > 0)
numHeats++;
int heats = numHeats;
//place heat and lane in each swimmer's object
int j = 0;
for (int i = 0; i < lastLanes; i++) ...{
Swimmer sw = swmrs[i];
sw.setLane(lanes[j++]);
sw.setHeat(heats);
if (j >= numLanes) ...{
heats--;
j=0;
}
}
//Add in last partial heat
if (j < numLanes)
heats--;
j = 0;
for (int i = lastLanes-1; i<count; i++) ...{
Swimmer sw = swmrs[i];
sw.setLane(lanes[j++]);
sw.setHeat(heats);
}
//copy from array back into ArrayList
swimmers = new ArrayList();
for (int i=0; i< count; i++)
swimmers.Add(swmrs[i]);
}
//--------------------------------
protected void sortUpwards() ...{
swmrs = new Swimmer[count];
for (int i=0; i < count; i++)
swmrs[i] = (Swimmer)swimmers[i];
for ( int i=0; i < count; i++) ...{
for (int j = i; j < count; j++) ...{
if (swmrs[i].getTime() > swmrs[j].getTime()) ...{
Swimmer swtemp = swmrs[i];
swmrs[i] = swmrs[j];
swmrs[j] = swtemp;
}
}
}
}
//--------------------------------
public override int getCount() ...{
return swimmers.Count ;
}
public override IEnumerator getSwimmers() ...{
return swimmers.GetEnumerator ();
}
//----------------------------------
public override int getHeats() ...{
return numHeats;
}
}
//循环排位
public class CircleSeeding:StraightSeeding //StraightSeeding的派生类CircleSeeding
...{
public CircleSeeding(ArrayList sw, int lanes):base(sw,lanes) ...{
seed();
}
//----------------------------
protected override void seed() ...{
int circle;
base.seed(); //do straight seed as default
if (numHeats >= 2 ) ...{
if (numHeats >= 3)
circle = 3;
else
circle = 2;
int i = 0;
for (int j = 0; j < numLanes; j++) ...{
for (int k = 0; k < circle; k++) ...{
swmrs[i].setLane(lanes[j]);
swmrs[i++].setHeat(numHeats - k);
}
}
}
}游泳者类Swimmer与使用到的其它类:
public class Swimmer //游泳者类
...{
private string firstName, lastName;
private int age;
private string club;
private float time;
private int heat, lane;
//--------------------------------------
public Swimmer(String dataline) ...{
StringTokenizer st = new StringTokenizer(dataline, " ");
string lineNumber = st.nextToken(); //ignore and discard
firstName = st.nextToken();
lastName = st.nextToken();
age = Convert.ToInt32 (st.nextToken().Trim());
club = st.nextToken().Trim();
string stime = st.nextToken().Trim();
int i = stime.IndexOf(":");
if (i > 0) ...{
stime = stime.Substring(0, i) + stime.Substring (i+1);
}
time = Convert.ToSingle ( stime);
}
//-------------------------------
public void setLane(int ln) ...{
lane = ln;
}
//-------------------------------
public int getLane() ...{
return lane;
}
//-------------------------------
public void setHeat(int ht) ...{
heat = ht;
}
//-------------------------------
public int getHeat() ...{
return heat;
}
//-------------------------------
public int getAge() ...{
return age;
}
//-------------------------------
public float getTime() ...{
return time;
}
//-------------------------------
public string getName() ...{
return firstName+" "+lastName;
}
//-------------------------------
public string getClub() ...{
return club;
}
}
/**//// <summary>
/// A simple file handlng class
/// </summary>
public class csFile
...{
private string fileName;
StreamReader ts;
StreamWriter ws;
private bool opened, writeOpened;
//-----------
public csFile() ...{
init();
}
//-----------
private void init() ...{
opened = false;
writeOpened = false;
}
//-----------
public csFile(string file_name) ...{
fileName = file_name;
init();
}
//-----------
public bool OpenForRead(string file_name)...{
fileName = file_name;
try ...{
ts = new StreamReader (fileName);
opened=true;
}
catch(FileNotFoundException e) ...{
return false;
}
return true;
}
//-----------
public bool OpenForRead() ...{
return OpenForRead(fileName);
}
//-----------
public string readLine() ...{
return ts.ReadLine ();
}
//-----------
public void writeLine(string s) ...{
ws.WriteLine (s);
}
//-----------
public void close() ...{
if (opened)
ts.Close ();
if(writeOpened)
ws.Close();
}
//-----------
public bool OpenForWrite() ...{
return OpenForWrite(fileName);
}
//-----------
public bool OpenForWrite(string file_name) ...{
try...{
ws = new StreamWriter (file_name);
fileName = file_name;
writeOpened = true;
return true;
}
catch(FileNotFoundException e) ...{
return false;
}
}
}
public class StringTokenizer ...{
private string data, delimiter;
private string[] tokens;
private int index;
public StringTokenizer(string dataLine) ...{
init(dataLine, " ");
}
private void init(String dataLine, string delim) ...{
delimiter = delim;
data = dataLine;
tokens = data.Split (delimiter.ToCharArray() );
index = 0;
}
public StringTokenizer(string dataLine, string delim) ...{
init(dataLine, delim);
}
public bool hasMoreElements() ...{
return (index < (tokens.Length));
}
public string nextToken() ...{
return nextElement();
}
public string nextElement() ...{
string s = tokens[index++];
while((s.Length <=0) && (index<tokens.Length ))
s = tokens[index++];
return s;
}
}
调用:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Seeding
...{
/**//// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
...{
private System.Windows.Forms.ListBox lsEvents;
private System.Windows.Forms.ListBox lsSwimmers;
/**//// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private ArrayList events;
private void init() ...{
//create array of events
events = new ArrayList ();
lsEvents.Items.Add ("500 Free");
lsEvents.Items.Add ("100 Free");
//and read in their data
events.Add (new TimedFinalEvent ("500free.txt", 6));
events.Add (new PrelimEvent ("100free.txt", 6));
}
public Form1()
...{
//
// Required for Windows Form Designer support
//
InitializeComponent();
init();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/**//// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
...{
if( disposing )
...{
if (components != null)
...{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form Designer generated code#region Windows Form Designer generated code
/**//// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
...{
this.lsEvents = new System.Windows.Forms.ListBox();
this.lsSwimmers = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// lsEvents
//
this.lsEvents.Location = new System.Drawing.Point(8, 24);
this.lsEvents.Name = "lsEvents";
this.lsEvents.Size = new System.Drawing.Size(112, 69);
this.lsEvents.TabIndex = 0;
this.lsEvents.SelectedIndexChanged += new System.EventHandler(this.lsEvents_SelectedIndexChanged);
//
// lsSwimmers
//
this.lsSwimmers.Location = new System.Drawing.Point(144, 24);
this.lsSwimmers.Name = "lsSwimmers";
this.lsSwimmers.Size = new System.Drawing.Size(192, 160);
this.lsSwimmers.TabIndex = 1;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(384, 205);
this.Controls.AddRange(new System.Windows.Forms.Control[] ...{
this.lsSwimmers,
this.lsEvents});
this.Name = "Form1";
this.Text = "Seeding Factory";
this.ResumeLayout(false);
}
#endregion
/**//// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
...{
Application.Run(new Form1());
}
private void lsEvents_SelectedIndexChanged(object sender, System.EventArgs e) ...{
int index = lsEvents.SelectedIndex ;
Event ev = (Event)events[index];
Seeding sd = ev.getSeeding();
IEnumerator en = sd.getSwimmers();
lsSwimmers.Items.Clear() ;
while(en.MoveNext ()) ...{
Swimmer sw = (Swimmer)en.Current ;
lsSwimmers.Items.Add(sw.getHeat()+" "+sw.getLane()+" "+sw.getName()+" "+sw.getTime());
}
}
}
}
相关文章推荐
- 工厂方法模式(Factory Method Pattern) 应用篇(上)
- 工厂方法模式(Factory Method Pattern)应用篇(直接使用工厂方法)
- 工厂方法模式(Factory Method Pattern)
- 第 5 章 工厂方法模式【Factory Method Pattern】
- 工厂方法模式(Factory Method Pattern)
- 工厂模式(Factory Pattern)之简单工厂,工厂方法模式(Factory Method Pattern),抽象工厂模式(Abstract Factory Pattern)
- 极速理解设计模式系列:9.工厂方法模式(Factory Method Pattern)
- 工厂方法模式(Factory Method Pattern,对象创建型模式)
- 工厂方法模式(Factory Method Pattern)
- 工厂方法模式 Factory Method Pattern
- 工厂方法模式(factory method pattern)
- 工厂方法模式(Factory Method Pattern)草书
- 工厂方法模式(Factory Method Pattern)
- Java设计模式:工厂方法模式(Factory Method Pattern)
- 六个创建型模式2:工厂方法模式-Factory Method Pattern 【学习难度:★★☆☆☆,使用频率:★★★★★】
- Net设计模式实例之工厂方法模式( Factory Method Pattern)
- 设计模式系列(五)工厂方法模式(Factory Method Pattern)
- 工厂方法模式(factory method pattern)
- 设计模式——工厂方法模式(Factory Method Pattern)