1. 程式人生 > >工廠方法模式【Factory Method Pattern】

工廠方法模式【Factory Method Pattern】

女媧補天的故事大家都聽說過吧,今天不說這個,說女媧創造人的故事,可不是“造人”的工作,這個詞被現代人濫用了。這個故事是說,女媧在補了天后,下到凡間一看,哇塞,風景太優美了,天空是湛藍的,水是清澈的,空氣是清新的,太美麗了,然後就待時間長了就有點寂寞了,沒有動物,這些看的到都是靜態的東西呀,怎麼辦?別忘了是神仙呀,沒有辦不到的事情,於是女媧就架起了八卦爐(技術術語:建立工廠)開始建立人,具體過程是這樣的:先是泥巴捏,然後放八卦爐裡烤,再扔到地上成長,但是意外總是會產生的:第一次烤泥人,茲茲茲茲~~,感覺應該熟了,往地上一扔,biu~,一個白人誕生了,沒烤熟!第二次烤泥人,茲茲茲茲茲茲茲茲~~,上次都沒烤熟,這次多烤會兒,往地上一扔,嘿,熟過頭了,黑人哪!第三次烤泥人,茲~茲~茲~,一邊烤一邊看著,嘿,正正好,Perfect!優品,黃色人種!【備註:RB 人不屬此列】這個過程還是比較有意思的,先看看類圖:(之前在論壇上有兄弟建議加類圖和原始檔,以後的模式都會加上去,之前的會一個一個的補充,目的是讓大家看著舒服,看著愉悅,看著就想要,就像是看色情小說一樣,目標,目標而已,能不能實現就看大家給我的信心了)


那這個過程我們就用程式來表現,首先定義一個人類的總稱:

package com.cbf4life;
/**
* @author cbf4Life [email protected]
* I'm glad to share my knowledge with you all.
* 定義一個人類的統稱
*/
public interface Human {
//首先定義什麼是人類

 //人是愉快的,會笑的,本來是想用smile表示,想了一下laugh更合適,好長時間沒有大笑了;
public void laugh();

//人類還會哭,代表痛苦
public void cry();

//人類會說話
public void talk();

} 
然後定義具體的人種:
package com.cbf4life;
/**
* @author cbf4Life [email protected]
* I'm glad to share my knowledge with you all.
* 黃色人種,這個翻譯的不準確,將就點吧
*/
public class YellowHuman implements Human {

public void cry() {
 System.out.println("黃色人種會哭");
 }
public void laugh() {
 System.out.println("黃色人種會大笑,幸福呀!");
 }
public void talk() {
 System.out.println("黃色人種會說話,一般說的都是雙位元組"); 
 }
} 

白色人種:
package com.cbf4life;
/**
* @author cbf4Life [email protected]
* I'm glad to share my knowledge with you all.
* 白色人種
*/
public class WhiteHuman implements Human {
public void cry() {
 System.out.println("白色人種會哭");
 }
public void laugh() {
 System.out.println("白色人種會大笑,侵略的笑聲");
 }
public void talk() {
 System.out.println("白色人種會說話,一般都是但是單位元組!");
 }
} 
黑色人種:
package com.cbf4life;
/**
* @author cbf4Life [email protected]
* I'm glad to share my knowledge with you all.
* 黑色人種,記得中學學英語,老師說black man是侮辱人的意思,不懂,沒跟老外說話
*/
public class BlackHuman implements Human {
public void cry() {
 System.out.println("黑人會哭"); 
 }
public void laugh() {
 System.out.println("黑人會笑");
 }
public void talk() {
 System.out.println("黑人可以說話,一般人聽不懂");
 }
} 
人種也定義完畢了,那我們把八卦爐定義出來:
package com.cbf4life;
import java.util.List;
import java.util.Random;
/**
* @author cbf4Life [email protected]
* I'm glad to share my knowledge with you all.
* 今天講女媧造人的故事,這個故事梗概是這樣的:
* 很久很久以前,盤古開闢了天地,用身軀造出日月星辰、山川草木,天地一片繁華
* One day,女媧下界走了一遭,哎!太寂寞,太孤獨了,沒個會笑的、會哭的、會說話的東東
* 那怎麼辦呢?不用愁,女媧,神仙呀,造出來呀,然後捏泥巴,放八卦爐(後來這個成了太白金星的寶
貝)中烤,於是就有了人:
* 我們把這個生產人的過程用Java程式表現出來:
*/
public class HumanFactory {

 //定一個烤箱,泥巴塞進去,人就出來,這個太先進了
public static Human createHuman(Class c){
 Human human=null; //定義一個型別的人類

 try {
 human = (Human)Class.forName(c.getName()).newInstance(); //產生一個
人種

 } catch (InstantiationException e) {//你要是不說個人種顏色的話,沒法烤,要白的
黑,你說話了才好烤

 System.out.println("必須指定人種的顏色");
 } catch (IllegalAccessException e) { //定義的人種有問題,那就烤不出來了,這是...
 System.out.println("人種定義錯誤!");
 } catch (ClassNotFoundException e) { //你隨便說個人種,我到哪裡給你製造去?!

 System.out.println("混蛋,你指定的人種找不到!");
 }
 return human;
 }

} 

然後我們再把女媧宣告出來:
package com.cbf4life;
/**
* @author cbf4Life [email protected]
* I'm glad to share my knowledge with you all.
* 首先定義女媧,這真是額的神呀
*/
public class NvWa {
public static void main(String[] args) {

 //女媧第一次造人,試驗性質,少造點,火候不足,缺陷產品
 System.out.println("------------造出的第一批人是這樣的:白人
-----------------");
 Human whiteHuman = HumanFactory.createHuman(WhiteHuman.class);
 whiteHuman.cry();
 whiteHuman.laugh();
 whiteHuman.talk();

 //女媧第二次造人,火候加足點,然後又出了個次品,黑人
 System.out.println("\n\n------------造出的第二批人是這樣的:黑人
-----------------");
 Human blackHuman = HumanFactory.createHuman(BlackHuman.class);
 blackHuman.cry();
 blackHuman.laugh();
 blackHuman.talk();

 //第三批人了,這次火候掌握的正好,黃色人種(不寫黃人,免得引起歧義),備註:RB人不屬
於此列
 System.out.println("\n\n------------造出的第三批人是這樣的:黃色人種
-----------------"); 
 Human yellowHuman = HumanFactory.createHuman(YellowHuman.class);
 yellowHuman.cry();
 yellowHuman.laugh();
 yellowHuman.talk()

 }
}

這樣這個世界就熱鬧起來了,人也有了,但是這樣建立太累了,神仙也會累的,那怎麼辦?神仙就想了:我塞進去一團泥巴,隨機出來一群人,管他是黑人、白人、黃人,只要是人就成(你看看,神仙都偷懶,何況是我們人),先修改類圖:


然後看我們的程式修改,先修改 HumanFactory.java,增加了 createHuman()方法:

package com.cbf4life;
import java.util.List;
import java.util.Random;
public class HumanFactory {

 //定一個烤箱,泥巴塞進去,人就出來,這個太先進了
public static Human createHuman(Class c){
 Human human=null; //定義一個型別的人類
 
 try {
 human = (Human)Class.forName(c.getName()).newInstance(); //產生一個
人種

 } catch (InstantiationException e) {//你要是不說個人種顏色的話,沒法烤,要白的
黑,你說話了才好烤

 System.out.println("必須指定人種的顏色");
 } catch (IllegalAccessException e) { //定義的人種有問題,那就烤不出來了,這是...

 System.out.println("人種定義錯誤!");
 } catch (ClassNotFoundException e) { //你隨便說個人種,我到哪裡給你製造去?!

 System.out.println("混蛋,你指定的人種找不到!");
 }
 return human;
 }

//女媧生氣了,把一團泥巴塞到八卦爐,哎產生啥人種就啥人種
public static Human createHuman(){
 Human human=null; //定義一個型別的人類

 //首先是獲得有多少個實現類,多少個人種
 List<Class> concreteHumanList =
ClassUtils.getAllClassByInterface(Human.class); //定義了多少人種
 //八卦爐自己開始想燒出什麼人就什麼人
 Random random = new Random();
 int rand = random.nextInt(concreteHumanList.size());

 human = createHuman(concreteHumanList.get(rand));

 return human;
 }
} 
然後看女媧是如何做的:
package com.cbf4life;
/**
* @author cbf4Life [email protected]
* I'm glad to share my knowledge with you all.
* 首先定義女媧,這真是額的神呀
*/
public class NvWa {
public static void main(String[] args) {

 //女媧第一次造人,試驗性質,少造點,火候不足,缺陷產品
 System.out.println("------------造出的第一批人是這樣的:白人
-----------------");
 Human whiteHuman = HumanFactory.createHuman(WhiteHuman.class);
 whiteHuman.cry();
 whiteHuman.laugh();
 whiteHuman.talk();

 //女媧第二次造人,火候加足點,然後又出了個次品,黑人
 System.out.println("\n\n------------造出的第二批人是這樣的:黑人
-----------------");
 Human blackHuman = HumanFactory.createHuman(BlackHuman.class);
 blackHuman.cry();
 blackHuman.laugh();
 blackHuman.talk();

 //第三批人了,這次火候掌握的正好,黃色人種(不寫黃人,免得引起歧義),備註:RB人不屬
於此列
 System.out.println("\n\n------------造出的第三批人是這樣的:黃色人種
-----------------");
 Human yellowHuman = HumanFactory.createHuman(YellowHuman.class);
 yellowHuman.cry();
 yellowHuman.laugh();
 yellowHuman.talk();

 //女媧煩躁了,愛是啥人種就是啥人種,燒吧

 for(int i=0;i<10000000000;i++){
 System.out.println("\n\n------------隨機產生人種了-----------------" +
i);
 Human human = HumanFactory.createHuman();
 human.cry();
 human.laugh();
 human.talk();
 }

 }
}

哇,這個世界熱鬧了!,不過還沒有完畢,這個程式你跑不起來,還要有這個類:
package com.cbf4life;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* @author cbf4Life [email protected] I'm glad to share my knowledge with you
* all.
*
*/
@SuppressWarnings("all")
public class ClassUtils {


//給一個介面,返回這個介面的所有實現類
public static List<Class> getAllClassByInterface(Class c){
 List<Class> returnClassList = new ArrayList<Class>(); //返回結果

 //如果不是一個介面,則不做處理
 if(c.isInterface()){
 String packageName = c.getPackage().getName(); //獲得當前的包名
 try {
 List<Class> allClass = getClasses(packageName); //獲得當前包下以
及子包下的所有類

 //判斷是否是同一個介面
 for(int i=0;i<allClass.size();i++){
 if(c.isAssignableFrom(allClass.get(i))){ //判斷是不是一個介面
 if(!c.equals(allClass.get(i))){ //本身不加進去
 returnClassList.add(allClass.get(i));
 }
 }
 }
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 } 
 }
 return returnClassList;
 }

//從一個包中查找出所有的類,在jar包中不能查詢
private static List<Class> getClasses(String packageName)
 throws ClassNotFoundException, IOException {
 ClassLoader classLoader = Thread.currentThread()
 .getContextClassLoader();
 String path = packageName.replace('.', '/');
 Enumeration<URL> resources = classLoader.getResources(path);
 List<File> dirs = new ArrayList<File>();
 while (resources.hasMoreElements()) {
 URL resource = resources.nextElement();
 dirs.add(new File(resource.getFile()));
 }
 ArrayList<Class> classes = new ArrayList<Class>();
 for (File directory : dirs) {
 classes.addAll(findClasses(directory, packageName));
 }
 return classes;
 }


private static List<Class> findClasses(File directory, String packageName)
throws ClassNotFoundException {
 List<Class> classes = new ArrayList<Class>();
 if (!directory.exists()) {
 return classes;
 }
 File[] files = directory.listFiles();
 for (File file : files) {
 if (file.isDirectory()) {
 assert !file.getName().contains(".");
 classes.addAll(findClasses(file, packageName + "." +
file.getName()));
 } else if (file.getName().endsWith(".class")) {
 classes.add(Class.forName(packageName + '.' +
file.getName().substring(0, file.getName().length() - 6)));
 }
 }
 return classes;
 } 
} 
告訴你了,這個 ClassUtils 可是個寶,用處可大了去了,可以由一個介面查詢到所有的實現類,也可以由父類查詢到所有的子類,這個要自己修改一下,動腦筋想下,簡單的很!完整的類圖如下:
我們來總結一下,特別是增加了 createHuman()後,是不是這個工廠的擴充套件性更好了?你看你要再加一個人種,只要你繼續整合 Human 介面成了,然後啥都不用修改就可以生產了,具體產多少,那要八卦爐說了算,簡單工廠模式就是這麼簡單,那我們再引入一個問題:人是有性別的呀,有男有女,你這怎麼沒區別,別急,這個且聽下回分解!工廠方法模式還有一個非常重要的應用,就是延遲始化(Lazy initialization),什麼是延遲始化呢?一個物件初始化完畢後就不釋放,等到再次用到得就不用再次初始化了,直接從記憶體過中拿到就可以了,怎麼實現呢,很簡單,看例子:
package com.cbf4life.advance;
import java.util.HashMap;
/**
* @author cbf4Life [email protected]
* I'm glad to share my knowledge with you all.
*/
@SuppressWarnings("all")
public class HumanFactory {
 //定義一個MAP,初始化過的Human物件都放在這裡
private static HashMap<String,Human> humans = new HashMap<String,Human>();

//定一個烤箱,泥巴塞進去,人就出來,這個太先進了
public static Human createHuman(Class c){
 Human human=null; //定義一個型別的人類

 try {
 //如果MAP中有,則直接從取出,不用初始化了
 if(humans.containsKey(c.getSimpleName())){
 human = humans.get(c.getSimpleName());
 }else{
 human = (Human)Class.forName(c.getName()).newInstance();
 //放到MAP中
 humans.put(c.getSimpleName(), human);
 }
 } catch (InstantiationException e) {//你要是不說個人種顏色的話,沒法烤,要白的
黑,你說話了才好烤

 System.out.println("必須指定人種的顏色");
 } catch (IllegalAccessException e) { //一定定義的人種有問題,那就烤不出來了,
這是...

 System.out.println("人種定義錯誤!");
 } catch (ClassNotFoundException e) { //你隨便說個人種,我到哪裡給你製造去?!

 System.out.println("混蛋,你指定的人種找不到!");
 }
 return human;
 }

} 
很簡單,就加粗那部分的程式碼,這個在類初始化很消耗資源的情況比較實用,比如你要連線硬體,或者是為了初始化一個類需要準備比較多條件(引數),通過這種方式可以很好的減少專案的複雜程度。

相關推薦

工廠方法模式Factory Method Pattern

女媧補天的故事大家都聽說過吧,今天不說這個,說女媧創造人的故事,可不是“造人”的工作,這個詞被現代人濫用了。這個故事是說,女媧在補了天后,下到凡間一看,哇塞,風景太優美了,天空是湛藍的,水是清澈的,空氣是清新的,太美麗了,然後就待時間長了就有點寂寞了,沒有動物,這些看的到都

Java設計模式工廠方法模式Factory Method Pattern

女媧補天的故事大家都聽說過吧,今天不說這個,說女媧創造人的故事,可不是“造人”的工作,這 個詞被現代人濫用了。這個故事是說,女媧在補了天后,下到凡間一看,哇塞,風景太優美了,天空是湛 藍的,水是清澈的,空氣是清新的,太美麗了,然後就待時間長了就有點寂寞了,沒有動物,這些看

設計模式之一---工廠方法模式Factory Method模式

          在設計模式中,Factory Method模式是一種比較簡單的設計模式,應用比較廣泛,但也是一種比較重要的設計模式之一。在很多地方我們都會看到xxxFactory這樣命名的類,那麼,什麼是Factory Method,為什麼要用這個模式,如何用Java語

模板方法模式Template Method Pattern

週三,9:00,我剛剛坐到位置,開啟電腦準備開始幹活。 “小三,小三,叫一下其它同事,到會議室,開會”老大跑過來吼,帶著淫笑。還不等大家坐穩,老 大就開講了, “告訴大家一個好訊息,昨天終於把牛叉模型公司的口子打開了,要我們做悍馬模型,雖然是第一個 車輛模型,但是我們有能力

模板方法模式Template Method Pattern

  下面橫線以上內容是借鑑別人的,為了表達對作者的敬意,不做不恰當的修改,我個人的總結在後面。 週三,9:00,我剛剛坐到位置,開啟電腦準備開始幹活。 “小三,小三,叫一下其它同事,到會議室,開會”老大跑過來吼,帶著淫笑。還不等大家坐穩,老 大就開講了, “告訴大家一

設計模式工廠方法模式Factory Method Pattern

/** * 工廠方法模式。 * @author Bright Lee */ public class FactoryMethodPattern { public static void main(String[] args) { Creator creator = null;

設計模式——模板方法模式Template Method Pattern

 我先設計個類圖: 非常簡單的實現,你要悍馬模型,我就給你悍馬模型,先寫個抽象類,然後兩個不同型號的模型實現類,那我們把這個程式實現出來: HummerModel抽象類的程式清單如下: package template.method.pattern; /** * 是

工廠方法模式Factory Method Pattern)。

定義: 定義一個用於建立物件的介面,讓子類決定例項化哪一個類。工廠方法使一個類的例項化延遲到其子類。 通用程式碼: 抽象產品類(Product)負責定義產品的共性 public abstract clas Product { // 產品類的公共方法 public

JAVA設計模式之 模板方法模式Template Method Pattern

一、概述     定義一個操作中演算法的框架,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。它是一種類行為型模式。 二、適用場景     適用於對一些複雜的操作/演算法進行步驟分割、抽取公共部分由抽象父類實現

工廠方法模式Factory Method

method 客戶端代碼 console 實例化 turn 簡單工廠 actor () blog 工廠方法模式:定義一個用於創建對象的接口,讓子類來決定實例化哪一個類。工廠方法使一個類的實例化延遲到子類。 簡單工廠模式的最大有點在於工廠勒種包含了必要的邏輯判斷,根據客戶

Java設計模式-工廠方法模式Factory Method

print blog -i pri cnp 三種模式 image void share 工廠方法模式(Factory Method) 工廠模式適合:凡是出現了大量的產品需要創建,並且具有共同的接口時,可以通過工廠方法模式進行創建。在以下的三種模式中,第一種如果傳入的字符串

C#設計模式(3)——工廠方法模式Factory Method

tor 對象 設計 黃色 post creator log clas 抽象工廠 在簡單工廠模式中通過工廠Factory獲取不同的對象,但是有一個明顯的缺點——簡單工廠模式系統難以擴展! 一旦添加新產品就不得不修改簡單工廠方法,這樣就會造成簡單工廠的實現邏輯過於復雜, 可以通

Java 開發 設計模式 ----工廠方法模式Factory Method

工廠方法模式(Factory Method) 工廠方法模式分為三種: 11、普通工廠模式,就是建立一個工廠類,對實現了同一介面的一些類進行例項的建立。首先看下關係圖: 舉一個傳送郵件和簡訊的例子。首先,建立二者的共同介面: public interface Sender {

程式碼設計模式工廠方法模式Factory Method

特點: 工廠方法是粒度很小的設計模式,因為模式的表現只是一個抽象的方法。提前定義用於建立物件的介面,讓子類決定例項化具體的某一個類,即在工廠和產品中間增加介面,工廠不再負責產品的建立,由介面針對不同條件返回具體的類例項,由具體類例項去實現。工廠方法模式是簡單工廠模式的衍生,

深入淺出設計模式——工廠方法模式Factory Method

轉自:https://www.cnblogs.com/Bobby0322/p/4179921.html 介紹在簡單工廠模式中,我們提到,工廠方法模式是簡單工廠模式的一個延伸,它屬於Gof23中設計模式的建立型設計模式。它解決的仍然是軟體設計中與建立物件有關的問題。它可以更好的處理客戶的需求變化。 引入我們

設計模式4——工廠方法模式factory-method

一、工廠方法模式說明 layout title folder permalink categories tags pattern Factory Method

大白話工廠方法模式Factory Method

目錄 簡單工廠模式缺陷 簡單工廠模式改造 工廠方法模式定義 工廠方法模式結構 工廠方法模式分析 參考文獻 簡單工廠模式缺陷 大白話簡單工廠模式(S

C#設計模式之十三模板方法模式(Template Method Pattern行為型

並集 client 變化 args 集中 pac 爸爸 rim 自己 原文:C#設計模式之十三模板方法模式(Template Method Pattern)【行為型】一、引言 “結構型”的設計模式已經寫完了,從今天我們開始講“行為型”設計模式。現在我們開始講【行為型】設

工廠模式Factory Method Pattern

n) 多態 產品 tel att new strac 代碼結構 減少 模式定義 工廠方法模式(Factory Method Pattern)又稱為工廠模式,也叫虛擬構造器(Virtual Constructor)模式或者多態工廠(Polymorphic Factory)模式

設計模式-簡單工廠模式/靜態工廠方法(Static Factory Method

使用原因 同一個呼叫,需要不同物件。統一通過工廠生產不同物件,建立物件的邏輯在工廠中。 定義 簡單工廠模式是屬於建立型模式,又叫做靜態工廠方法(Static Factory Method)模式,不屬於23種GOF設計模式。簡單工廠模式是由一個工廠物件決定創建出哪一種產品類