創建模式:簡單工廠模式(靜態工廠方法)
描述:由一個工廠對象決定創建出哪一種產品類的實例。
工廠模式專門負責將大量有共同接口的類實例化。
抽象類/接口 |
工廠類--Creates---->子類/實現類
Fruit接口有三個方法:
public interface Fruit
{
void grow();
void harvest();
void plant();
}
蘋果,草莓,葡萄都實現了這一接口,其中葡萄有有籽無籽之分(seedness:boolean),蘋果有樹的年齡屬性(treeAge:int)。
//Grape
public class Grape implements Fruit
{
public void grow()
{
System.out.println("Grape is growing...");
}
public void harvest()
{
System.out.println("Grape has been harvested.");
}
public void plant()
{
System.out.println("Grape has been planted.");
}
public boolean getSeedless()
{
return seedless;
}
public void setSeedless(boolean seedless)
{
this.seedless = seedless;
}
private boolean seedless;
}
//Strawberry
public class Strawberry implements Fruit
{
public void grow()
{
System.out.println("Strawberry is growing...");
}
public void harvest()
{
System.out.println("Strawberry has been harvested.");
}
public void plant()
{
System.out.println("Strawberry has been planted.");
}
}
//Apple
public class Apple implements Fruit
{
public void grow()
{
System.out.println("Apple is growing...");
}
public void harvest()
{
System.out.println("Apple has been harvested.");
}
public void plant()
{
System.out.println("Apple has been planted.");
}
public int getTreeAge(){ return treeAge; }
public void setTreeAge(int treeAge){ this.treeAge = treeAge; }
private int treeAge;
}
FruitGardener為園丁類(工廠類):
public class FruitGardener
{
public static Fruit factory(String which) throws BadFruitException
{
if (which.equalsIgnoreCase("apple"))
{
return new Apple();
}
else if (which.equalsIgnoreCase("strawberry"))
{
return new Strawberry();
}
else if (which.equalsIgnoreCase("grape"))
{
return new Grape();
}
else
{
throw new BadFruitException("Bad fruit request");
}
}
}
可以看出園丁類提供了一個靜態工廠方法,在客戶端的調用下,這個方法創建客戶端所需要的水果對象,如果客戶端的請求是系統所不支持的,則工廠方法拋出異常。在使用時,客戶端只需要調用FruitGardener的靜態方法factory()即可。
工廠類角色:擔任這個角色的是工廠方法模式的核心,含有與應用緊密相關的商業邏輯,由一個具體java類實現。
抽象產品角色:擔任這個角色的類是由工廠方法模式所創建的對象的父類,或者它們共同擁有的接口。由一個JAVA接口或者JAVA抽象類實現。
具體產品角色:工廠方法模式所創建的任何對象都是這個角色的實例,由一個JAVA具體類實現。
public class Creator{
public static Product factory()
{
return new ConcreteProduct();
}
}
抽象產品角色的主要目的是給所有具體產品提供一個共同的類型,在最簡單的情況下,可以簡化為一個標識接口,所謂標識接口,就是沒有聲明任何方法的空接口。
每個工廠類可以有多于一個的工廠方法,分別負責創建不同的產品對象。
如果系統只有一個具體產品角色的話,抽象產品角色可以省略。
有些情況下,工廠角色可以由抽象角色扮演,典型的應用是java.text.DateFormat。
三個角色全部合并:抽象角色被省略,工廠角色可以與具體產品角色合并。
循環使用產品對象
循環使用一個產品對象:每一次客戶端調用工廠方法時,工廠方法總是提供同一個對象,工廠對象可以使用一個屬性來存儲這個產品對象。
循環使用一組對象:使用一個聚集對象來存儲這個才產品對象。
簡單工廠模式的優點:模式的核心是工廠類,這個類含有必要的判斷邏輯,可以決定在什么時候創建哪一個產品類的實例,而客戶端可以免除直接創建產品對象的責任,而僅僅負責消費產品,實現了對責任的分割。
簡單工廠模式的缺點:當產品類有復雜的多層次等級結構時,工廠類只有一個,只能以不變應萬變。工廠類無所不能,一旦工廠類不能工作,整個系統都會受到影響。
一個類里的邏輯太多,使得系統擴展困難---->工廠方法模式中克服。
使用靜態方法作為工廠方法,不能由子類繼承,難于形成基于繼承的等級結構--->工廠方法模式中克服。
簡單工廠角色只在有限的程度上支持OCP:允許客戶端相對獨立于產品創建的過程,并且在系統中引入新產品的時候無須許該客戶端,這一點支持OCP;但是,新產品引入到系統中去的時候,就需要修改工廠類,將必要的邏輯加入到工廠類中,這一點不支持OCP。
應用:java.text.DateFormat:getTimeInstance():DateFormat
public final static DateFormat getTimeInstance(){}
使用靜態工廠方法將具體子類的實例化的工作隱藏起來,從而客戶端不必考慮如何將具體子類實例化,因為抽象類DateFormat會提供它的合適的具體子類的實例。