1. 程式人生 > >簡單工廠(Java)

簡單工廠(Java)

簡單工廠不是一個標準的設計模式,但是因其常用,簡單而又神奇,故把它放到設計模式中。

一:介面的回顧

1:Java中介面的概念

在Java中介面是一種特殊的抽象類,根一般的抽象類相比,接口裡面的所有方法都是抽象方法,接口裡面的所有屬性都是常量。即接口裡面只有方法定義而沒有任何方法實現。

2:介面的用途

通常用介面來定義實現類的外觀,也就是實現類的行為定義,用來約束實現類的行為。介面就相當於一份契約,根據外部應用需要的功能,約定了實現類應該要實現的功能,但是具體的實現類除了實現介面約定的功能外,還可以根據需要實現其他一些功能,這是允許的,也就是說實現類的功能包含但不僅限於介面約束的功能。

通過使用介面,可以實現不相關的相同行為,而不需要考慮這些類之間的層次關係,介面就是實現類對外的外觀。

3:介面的思想

根據介面的作用和用途,濃縮下來,介面的思想就是“封裝隔離”

通常提到的封裝是指對資料的封裝,但是這裡的封裝是指“對被隔離體的行為的封裝”,或者是“對被隔離體的職責的封裝”;而隔離指的是外部呼叫和內部實現,外部呼叫只能通過介面進行呼叫,外部呼叫是不知道內部具體實現的,也就是說外部呼叫和內部實現是被介面隔離開的。

4:使用介面的好處

由於外部呼叫和內部實現被介面隔離開了,那麼只要介面不變,內部實現的變化就不會影響到外部應用,從而使得系統更靈活,具有更好的擴充套件性和可維護性,這也就是所謂“介面是系統可插拔性的保證”這句話的意思。

5:介面和抽象類的選擇

優先選用介面;

在既要定義子類的行為,又要為子類提供公共的功能時應選擇抽象類。

二:面向介面程式設計

面向介面程式設計是Java程式設計中一個重要的原則。

在Java程式設計裡面,非常講究層的劃分和模組的劃分。通常按照三層來劃分Java程式,即表現層、邏輯層、資料層,它們之間都要通過介面來通訊。

在每一個層裡面,又有很多小模組,每個小模組對外則是一個整體,所以一個模組對外應該提供介面,其他地方需要使用到這個模組的功能時,可以通過此介面來進行呼叫。這也就是常說的“介面是被其隔離部分的外觀”。基本的三層結構如下圖:


在一個層內部的各個模組間的互動要通過介面。


元件:從設計上講,元件就是完成一定功能的封裝體。小到一個類,大到一個系統,都可以稱為元件(因為一個小系統放到一個更大的系統裡面去,也就當個元件而已)。事實上,從設計的角度看,系統、子系統、模組、元件等說的其實是同一回事,都是完成一定功能的封裝體(只不過功能多少不同而已)。

三:實現下面功能(不用模式)


1:程式碼實現:

/**
 * 某個介面(通用的、抽象的、非具體的功能)
 * @author Peter
 */
public interface Api {
	
	//某個具體功能的方法定義,用test1演示
	public void test1(String s);
}
/**
 * 對介面的實現
 * @author Peter
 */
public class Impl implements Api {

	public void test1(String s) {

		System.out.println("Now In Impl. The Input s == " + s);
	}
}
/**
 * 客戶端;測試使用Api介面
 * @author Peter
 */
public class Client {

	public static void main(String[] args) {
		Api api = new Impl();
		api.test1("別緊張只是個測試而已!");
	}
}

2:對實現的程式碼小思

在Api api = new Impl( );這行在客戶端的程式碼使得客戶端不但知道了Api介面還知道了其實現類Impl。介面的思想是“封裝隔離”,而實現類Impl應該是被介面Api封裝並同客戶端隔離開的,即客戶端根本就應該不知道具體的實現類是Impl。

於是乎我們就拿走new Impl( );但是我們卻無法得到Api介面物件。就像現在的Client,它知道要使用Api介面,但是不知道由誰實現,也不知道如何實現,從而得不到介面物件,就無法使用介面,那該怎麼辦?於是乎簡單工廠就來了。

四:簡單工廠來了

用來解決上述問題的一個合理的解決方案就是簡單工廠。

1:簡單工廠的定義

提供一個建立物件例項的功能,而無須關心其具體實現。被建立例項的型別可以是介面、抽象類,也可以是具體的類。

2:用簡單工廠解決問題思路

分析上面的問題,雖然不能讓模組外部知道模組內部的具體實現,但是模組內部是可以知道實現類的,而且建立介面是需要具體實現類的。

那麼,我們在模組內部新建一個類,在這個類裡面來建立介面,然後把建立好的介面返回給客戶端,這樣,外部應用就只需要根據這個類來獲取相應的介面物件,然後就可以操作介面定義的方法了。把這樣的物件稱為簡單工廠,就叫它Factory。

這樣一來,客戶端就可以通過Factory來獲取需要的介面物件,然後呼叫介面的方法來實現需要的功能,而且客戶端也不用再關心具體的實現了。

3:簡單工廠結構和說明


Api:定義客戶所需要的功能介面;

Impl:具體實現Api的實現類,可能會有多個

Factory:工廠,選擇合適的實現類來建立Api介面物件。

Client:客戶端,通過Factory來獲取Api介面物件,然後面向Api介面程式設計。

4:簡單工廠示例程式碼

/**
 * 介面的定義,該介面可以通過簡單工廠來建立
 * @author Peter
 */
public interface Api {
	
	//具體功能方法的定義
	public void operation(String str);
}
/**
 * 介面的具體實現物件A
 * @author Peter
 */
public class ImplA implements Api {

	public void operation(String str) {
		System.out.println("ImplA s == " + str);
	}
}
/**
 * 介面的具體實現物件B
 * @author Peter
 */
public class ImplB implements Api {

	public void operation(String str) {
		System.out.println("ImplB s == " + str);
	}
}
/**
 * 工廠類用於建立Api物件
 * @author Peter
 */
public class Factory {

	//具體建立Api物件的方法,int condition示意,從外部傳入的選擇條件
	public static Api createApi(int condition){
		/**
		 * 應該根據某些條件去選擇究竟建立哪一個具體的實現物件
		 * 這些條件可以從外部傳入,也可以從其他途徑獲取
		 * 如果只有一個實現,可以省略條件,因為沒有選擇的必要
		 */
		Api api = null;
		if(condition == 1){
			api = new ImplA();
		}else if(condition == 2){
			api = new ImplB();
		}
		return api;
	}
}
/**
 * 客戶端,使用Api介面
 * @author Peter
 */
public class Client {

	public static void main(String[] args) {
		//通過簡單工廠來獲取介面物件
		Api api = Factory.createApi(1);
		api.operation("正在使用簡單工廠,選擇條件為1");
	}
}

五:模式講解

表面上看起來在客戶端的new Impl( )放到了Factory中,這沒有什麼區別啊,可是特殊就在Factory的位置,Factory是位於封裝體內部的,即簡單工廠是跟介面和實現類在一塊的,算是封裝體內部的一個類,所以Factory知道實現類是沒有關係的。


上圖的虛線框,就好比是一個元件的包裝邊界,表示介面、實現類和工廠類組合成了一個元件。在這個封裝體裡面,只有介面和工廠是對外的,即讓外部知道並使用,故意洩露了一些在虛線框的外面,而具體的實現類是不對外的,被完全包含在虛線框內。

對於客戶端而言,只是知道了介面Api和簡單工廠Factory,通過Factory就可以獲得Api了,這樣就達到了讓Client在不知道具體實現類的情況下獲取介面Api。

所以看似簡單地將new Impl()這句話從客戶端裡面移動到了簡單工廠裡面,其實是有了實質的變化的。

1:簡單工廠的功能

利用簡單工廠建立介面,但是也可以利用簡單工廠建立抽象類或者普通類的例項。

2:靜態工廠

使用簡單工廠的時候,通常不用建立簡單工廠類的類例項,沒有建立例項的必要。因此可以把簡單工廠類實現成一個工具類,直接使用靜態方法就可以了。即簡單工廠的方法通常是靜態的,所以也被稱為靜態工廠。如果要防止客戶端無謂地創造簡單工廠例項,還可以把簡單工廠的構造方法私有化了。

3:萬能工廠

一個簡單工廠可以包含很多用來構造東西的方法,這些方法可以建立不同的介面、抽象類或者是類例項。一個簡單工廠理論上可以構造任何東西,所以又稱之為“萬能工廠”。

4:簡單工廠建立物件的範圍

理論上,簡單工廠什麼都可以建立,但對於簡單工廠可建立物件的範圍,通常不要太大。建議控制在一個獨立的元件級別或一個模組級別,也就是一個元件或模組簡單工廠。否則這個簡單工廠類會職責不明,有點大雜燴的感覺。

5:簡單工廠呼叫的順序示意圖


6:簡單工廠命名

類名稱建議為“模組名稱+Factory”。比如,使用者模組的工廠就稱為UserFactory。

方法名稱通常稱為“get+介面名稱”或者是“create+介面名稱”。比如,有一個介面名為UserEbi,那麼方法名稱通常為getUserEbi或者是createUserEbi。

六:簡單工廠中方法的寫法

雖然說簡單工廠的方法大多是用來建立介面的,但是仔細分析就會發現,真正能實現功能的是具體的實現類,這些實現類是已經做好的,並不是真的要靠簡單工廠來創造出來的,簡單工廠的方法無外乎就是:實現了選擇一個合適的實現類來使用。

故簡單工廠方法的內部主要實現的功能是“選擇合適的實現類”來建立例項物件。既然要實現選擇,那麼就需要選擇的條件或者是選擇的引數,選擇條件或者是引數來源有以下幾種:

1:來源於客戶端,有Client來傳入引數

/**
 * 介面的定義,該介面可以通過簡單工廠來建立
 * @author Peter
 */
public interface Api {
	
	//具體功能方法的定義
	public void operation(String str);
}
/**
 * 介面的具體實現物件A
 * @author Peter
 */
public class ImplA implements Api {

	public void operation(String str) {
		System.out.println("ImplA s == " + str);
	}
}
/**
 * 介面的具體實現物件B
 * @author Peter
 */
public class ImplB implements Api {

	public void operation(String str) {
		System.out.println("ImplB s == " + str);
	}
}
/**
 * 工廠類用於建立Api物件
 * @author Peter
 */
public class Factory {

	//具體建立Api物件的方法,int condition示意,從外部傳入的選擇條件
	public static Api createApi(int condition){
		/**
		 * 應該根據某些條件去選擇究竟建立哪一個具體的實現物件
		 * 這些條件可以從外部傳入,也可以從其他途徑獲取
		 * 如果只有一個實現,可以省略條件,因為沒有選擇的必要
		 */
		Api api = null;
		if(condition == 1){
			api = new ImplA();
		}else if(condition == 2){
			api = new ImplB();
		}
		return api;
	}
}
/**
 * 客戶端,使用Api介面
 * @author Peter
 */
public class Client {

	public static void main(String[] args) {
		//通過簡單工廠來獲取介面物件
		Api api = Factory.createApi(1);
		api.operation("正在使用簡單工廠,選擇條件為1");
	}
}

2:來源於配置檔案,從配置檔案獲取用於判斷的值

/**
 * 介面的定義,該介面可以通過簡單工廠來建立
 * @author Peter
 */
public interface Api {
	
	//具體功能方法的定義
	public void operation(String str);
}
/**
 * 介面的具體實現物件A
 * @author Peter
 */
public class ImplA implements Api {

	public void operation(String str) {
		System.out.println("ImplA s == " + str);
	}
}
/**
 * 介面的具體實現物件B
 * @author Peter
 */
public class ImplB implements Api {

	public void operation(String str) {
		System.out.println("ImplB s == " + str);
	}
}
Factory.properties
ImplClassA=com.simplefactory.demo03.ImplA
ImplClassB=com.simplefactory.demo03.ImplB
public class Factory {

	/**
	 * 具體建立Api的方法,根據配置檔案的引數來建立介面
	 * @return
	 */
	public static Api createApi(){
		//直接讀取配置檔案來獲取需要建立例項的類
		Properties p = new Properties();
		InputStream input = null;
		try {
			input = Factory.class.getResourceAsStream("Factory.properties");
			p.load(input);
		} catch (IOException e) {
			System.out.println("裝載配置檔案工廠出錯,具體的堆疊資訊如下:");
			e.printStackTrace();
		}finally{
			try {
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		Api api = null;
		try {
			api = (Api)Class.forName(p.getProperty("ImplClassB")).newInstance();
		} catch (Exception e) {

			e.printStackTrace();
		}
		return api;
	}
}
public class Client {
	public static void main(String[] args) {
		Api api = Factory.createApi();
		api.operation("讀取配置檔案方式的簡單工廠");
	}
}

3:來源於程式執行期的某個值,比如從快取中獲取某個執行期的值。

七:簡單工廠的優缺點

1:簡單工廠有點:

(1)幫助封裝(簡單工廠雖然很簡單,但是很友好地幫助我們實現了元件的封裝,然後讓元件外部能真正面向介面程式設計)

(2)解耦(通過簡單工廠,實現了客戶端和具體實現類的解耦,如上面例子,客戶端根本就不知道具體是由誰來實現,也不知道如何實現,客戶端只是通過工廠獲取它需要的介面物件)。

2:簡單工廠缺點

(1)可能增加了客戶端的複雜度

如果通過客戶端的引數來選擇具體的實現類,那麼就必須讓客戶端能理解各個引數所代表的具體功能和含義,這樣會增加客戶端使用的難度,也部分暴露了內部實現,這種情況可以選用可配置的方式來實現。

(2)不方便擴充套件子工廠

私有化簡單工廠的構造方法,使用靜態方法來建立介面,也就不能通過寫簡單工廠類的子類來改變建立介面的方法的行為了。不過,通常情況下是不需要為簡單工廠建立子類的。

八:小思簡單工廠

1:簡單工廠的本質是:選擇實現

注意簡單工廠的重點在選擇,實現是已經做好了的。就算實現再簡單,也要由具體的實現類來實現,而不是在簡單工廠裡面來實現。簡單工廠的目的在於客戶端來選擇相應的實現,從而使得客戶端和實現之間解耦。這樣一來,具體實現發生了變化,就不用變動客戶端了,這個變化會被簡單工廠吸收和遮蔽掉。

實現簡單工廠的難度在於“如何選擇”實現,上面說了幾種傳遞引數的方法,那都是靜態的引數,還可以實現成為動態的引數。比如,在執行期間,有工廠來讀取某個記憶體的值,或者是去讀取資料庫中的值,然後根據這個值來選擇具體的實現等。

2:何時使用簡單工廠

(1)如果想要完全封裝隔離具體實現,讓外部只能通過介面來操作封裝體,那麼可以選用簡單工廠,讓客戶端通過工廠來獲取相應的介面,而無須關係具體的實現。

(2)如果想要把對外建立物件的職責集中管理和控制,可以選用簡單工廠,一個簡單工廠可以建立很多的、不相關的物件,可以把對外建立物件的職責集中到一個簡單工廠來,從而實現集中管理和控制。



相關推薦

簡單工廠Java

簡單工廠不是一個標準的設計模式,但是因其常用,簡單而又神奇,故把它放到設計模式中。一:介面的回顧1:Java中介面的概念在Java中介面是一種特殊的抽象類,根一般的抽象類相比,接口裡面的所有方法都是抽象方法,接口裡面的所有屬性都是常量。即接口裡面只有方法定義而沒有任何方法實現

MQTT簡單demojava

停用 隊列 設置 msg 的區別 多個 指定 throwable ica   上次已經簡單的談了一些MQTT協議的一些知識,今天就來就上次的知識具體的Java實現。   現在就來具體說說實現這一步吧。中間的時間也是有點久。   MQTT消息的發送和訂閱都是依賴MQTT服務器

實現簡單工廠

//建立一個工廠的環境 //賣車的商店 function CarShop(){}; CarShop.prototype = { constructor : CarShop, //還原構造器 sellC

Javascript設計模式之簡單工廠

建立型設計模式-簡單工廠模式 簡單工廠模式(Simple Factory):又稱之為靜態工廠模式,由一個工廠物件建立某一種產品物件類的例項。主要用來建立同一類物件。 多類單例項法 為了加深我們的理解,設定以下需求。假設一個大型超市賣各種東西,

設計模式-簡單工廠Demo

簡介          工廠都是建立型模式、用來NEW類的、本文章用一個故事講述了簡單工廠模式 故事 在遙遠的未來、chenchen我生活條件不錯、但是每天都要做飯、chenchen很懶、只想吃、不想

luceneAPI的簡單使用java

lucene是一個全文檢索引擎工具包,下面來簡單的介紹下Lucene常用的API介紹 1:對一個檔案下面的所有檔案進行索引建立: import java.io.BufferedReader; import java.io.File; import java

設計模式簡單介紹Java語言-- 工廠方法模式

設計模式簡單介紹(Java語言) – 工廠方法模式 1.工廠方法模式的定義: 工廠方法模式(FACTORY METHOD)是一種常用的物件建立型設計模式,此模式的核心精神是封裝類中不變的部分,提取其中個性化善變的部分為獨立類,通過依賴注入以達到解耦

Java靜態檢測工具/Java代碼規範和質量檢查簡單介紹

pub 詳細 職責 web 循環 問題: 集成 死鎖 參考 靜態檢查: 靜態測試包括代碼檢查、靜態結構分析、代碼質量度量等。它可以由人工進行,充分發揮人的邏輯思維優勢,也可以借助軟件工具自動進行。代碼檢查代碼檢查包括代碼走查、桌面檢查、代碼審查等,主要檢查代碼和設計的一致

javaselenium webdriver學習---實現簡單的翻頁,將頁面內容的標題和標題鏈接取出

prop imp current inter 並且 常見問題 activity num div selenium webdriver學習---實現簡單的翻頁,將頁面內容的標題和標題鏈接取出; 該情況適合能能循環page=1~n,並且每個網頁隨著循環可以打開的情況, 註意一定

簡單易用的參數校驗北京PK10平臺出租和版本校驗方式java

else runtime boot java pri conf utils 短信 con 步驟是:配置數據校驗規則(多條)>>>>在控制器上添加校驗註解>>>>使用攔截器攔截校驗參數(獲取註解,初始化校驗規則(第一次),取出參

Java簡單演算法陣列

 找出陣列中的最大值 //找出陣列中的最大值 static void getMax() { int a[] = {15, 35, 18, 87, 48, 6, 84, 57, 98}; int max = a[0];

設計模式2——建立型——工廠相關:簡單工廠Simple factory工廠方法Factory method,抽象工廠Abstract factory

概要 這裡試圖描述23個設計模式中的兩個工廠(Factory)相關的設計模式:工廠方法(Factorymethod),抽象工廠(Abstract factory)。 注意點: 這兩個都屬於建立型設計模式。 由於這兩個設計模式都

負載均衡演算法---Java簡單實現2

上一篇介紹了負載均衡的輪詢,隨機,跟hash演算法,這邊我們一起了解下,加權的輪詢以及加權的隨機。其實理解好了輪詢跟隨機演算法,再加權的話其實是差不多的。 看面通過程式碼來了解: (1)為了不重複建立一個server列表,我們先建立一個共有的server列表,如下: pu

負載均衡演算法---Java簡單實現1

最近,大夥常在談論什麼負載均衡,什麼伺服器的,而自己對於這一塊也是不太理解深入模糊,然後就去看書學習,印證自己的想法。下面是自己的一些總結吧:   比較常用的負載均衡演算法,有下面的這一些: (1)輪詢(其實就是迴圈) (2)隨機 (3)hash (4)加權輪詢

基於《仙劍奇俠傳柔情版》利用Java簡單實現

基於《仙劍奇俠傳柔情版》利用Java的簡單實現(一) 2018-12-01 23:55:36   by Louis  一,新建一個類GameFrame.class,具體程式碼如下: package firstDemo; import javax.swing.JF

《仙劍奇俠傳柔情版》Java簡單實現

基於《仙劍奇俠傳柔情版》Java的簡單實現(二) 2018-12-02 by louis     需要上次的GameFrame.class中視窗框架承載:https://www.cnblogs.com/louis6575/p/10051873.html 當時沒有學過JButt

Java集合框架詳解--Collection介面簡單介紹

一、Collection介面簡單介紹        Collection介面是處理物件集合的根介面,其中定義了很多對元素進行操作的方法。Collection介面有兩個主要的子介面List和Set,注意Map不是Collection的子介面。 Collection介面中的方

抽象工廠模式Java

工廠模式可以分為:簡單工廠模式,工廠方法模式,抽象工廠模式。 簡單工廠模式就沒什麼好說的了,無非是所有的東西都寫在一個類裡面,要什麼就呼叫什麼,如果要新增新的方法也是到這類裡面新增,程式碼很多,看起來也是很亂,就像一個大工廠,什麼都在裡面。擴充套件性很低。 而工廠方法模式

c++建立型設計模式--工廠模式--簡單工廠單個產品的構建

思想 主要是對於單個簡單的產品進行構建 基類 #pragma once #include <iostream> /** * 基類指標 *Date :[10/12/2018 ] *Aut

設計模式之工廠方法模式java

1、概念 工廠方法模式(FACTORY METHOD)是一種常用的物件建立型設計模式,此模式的核心精神是封裝類中不變的部分,提取其中個性化善變的部分為獨立類,通過依賴注入以達到解耦、複用和方便後期維護拓展的目的。它的核心結構有四個角色,分別是抽象工廠;具體工廠;抽象產品;