Java設(shè)計(jì)模式中的簡(jiǎn)單工廠模式解析
一、定義
定義: 提供一個(gè)創(chuàng)建對(duì)象實(shí)例的功能,而無(wú)須關(guān)心其具體實(shí)現(xiàn)。被創(chuàng)建實(shí)例的類型可以是接口、抽象類,也可以是具體的類。
PS: 我們都知道JAVA思想一直推崇“面向接口編程”。而接口的思想就是“封裝隔離”,即外部調(diào)用只能通過(guò)接口進(jìn)行調(diào)用,外部調(diào)用并不知道內(nèi)部具體實(shí)現(xiàn),也就是說(shuō)外部調(diào)用和內(nèi)部實(shí)現(xiàn)是被接口隔離開的。那么只要接口不變,內(nèi)部實(shí)現(xiàn)的變化就不會(huì)影響到外部應(yīng)用,使得系統(tǒng)更加靈活,增加系統(tǒng)的擴(kuò)展性和可維護(hù)性,這也就是所謂的“接口是系統(tǒng)可拔插的保證”。
二、案例
假設(shè)有一個(gè)接口叫Api,然后有一個(gè)實(shí)現(xiàn)類Impl實(shí)現(xiàn)了它,如何在客戶端使用這個(gè)接口? So Easy !我們可以很快畫出這個(gè)案例的類圖并寫出代碼。
/** * @ClassName Api * @Description: 定義一個(gè)接口 * @author Jerry * @date 2016年3月26日 下午11:27:32 */ public interface Api { /** * @Description: 簡(jiǎn)單實(shí)現(xiàn),傳入字符串打印 * @param @param str */ public void test(String str); } /** * @ClassName Impl * @Description: 實(shí)現(xiàn)Api接口 * @author Jerry * @date 2016年3月27日 上午10:12:27 */ public class Impl implements Api { @Override public void test(String str) { System.out.println(str); } } /** * @ClassName Client * @Description: 外部調(diào)用 * @author Jerry * @date 2016年3月27日 上午10:13:35 */ public class Client { public static void main(String[] args) { Api api = new Impl(); api.test("最愛你的人是我,你怎么舍得我難過(guò)"); } }
三、使用模式的情況
如果我們仔細(xì)想想就會(huì)發(fā)現(xiàn),這樣的設(shè)計(jì)違背了接口的設(shè)計(jì)原則。因?yàn)榭蛻舳吮仨氈滥男┚唧w實(shí)例實(shí)現(xiàn)了接口,并沒有實(shí)現(xiàn)“封裝隔離”。其實(shí)這里只是用到了接口的多態(tài)功能。
/** * @ClassName Factory * @Description: 其余代碼和之前沒有變化,只增加這樣工廠類即可 * @author Jerry * @date 2016年3月27日 上午10:23:30 */ public class Factory { /** * @Description: 通常把Factory當(dāng)成一個(gè)工具類,不需要?jiǎng)?chuàng)建類實(shí)例,所以直接使用靜態(tài)方法 * @param 當(dāng)然可以添加參數(shù),使得客戶端可以選擇自己想要初始化的實(shí)例,但不推薦,后面會(huì)解釋原因 * @return Api 返回一個(gè)具體實(shí)現(xiàn) * @throws */ public static Api createApi() { return new Impl(); } } /** * @ClassName Client * @Description: 外部調(diào)用 * @author Jerry * @date 2016年3月27日 上午10:13:35 */ public class Client { public static void main(String[] args) { // Api api = new Impl(); Api api = Factory.createApi(); //無(wú)須在客戶端直接new具體實(shí)現(xiàn) api.test("最愛你的人是我,你怎么舍得我難過(guò)"); } }
一個(gè)簡(jiǎn)單工廠理論上可以創(chuàng)造任何東西,所以又稱為“萬(wàn)能工廠”。簡(jiǎn)單工廠的本質(zhì)在于“選擇合適的實(shí)現(xiàn)類”,既然要選擇,那么肯定需要用戶去指定參數(shù),通常有以下3種:
- 來(lái)源于客戶端,指定參數(shù)。例如我們可以在創(chuàng)建實(shí)例的方法中加入?yún)?shù),這樣客戶端可以傳入具體參數(shù)來(lái)獲得自己想要的實(shí)例。但是這樣會(huì)帶來(lái)一個(gè)問題,客戶端必須知道每個(gè)參數(shù)的含義功能,使得向用戶暴露了一定的內(nèi)部實(shí)現(xiàn)細(xì)節(jié)。通常我們使用配置文件的寫法。
- 來(lái)源于配置文件,從配置文件獲取用于判斷的值,下文會(huì)具體介紹。
- 來(lái)源于程序運(yùn)行期的某個(gè)值,比如內(nèi)存中的某個(gè)變量值,此方法屬于動(dòng)態(tài)實(shí)現(xiàn)。
- 使用配置文件進(jìn)行優(yōu)化 我們使用properties文件,放在Factory同一個(gè)包下。
- ImplClass=simpleFactory.Impl 然后修改Factory類,其余不變:
/** * @ClassName Factory * @Description: 其余代碼和之前沒有變化,只增加這樣工廠類即可 * @author Jerry * @date 2016年3月27日 上午10:23:30 */ public class Factory { public static Api createApi() { Properties properties = new Properties(); InputStream in = null; try { in = Factory.class.getResourceAsStream("factory.properties"); properties.load(in); } catch (IOException e) { e.printStackTrace(); }finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } Api api = null; try { //使用反射創(chuàng)建實(shí)例 api = (Api) Class.forName(properties.getProperty("ImplClass")).newInstance(); } catch (Exception e) { e.printStackTrace(); } return api; } /** * @Description: 通常把Factory當(dāng)成一個(gè)工具類,不需要?jiǎng)?chuàng)建類實(shí)例,所以直接使用靜態(tài)方法 * @param 當(dāng)然可以添加參數(shù),使得客戶端可以選擇自己想要初始化的實(shí)例,但不推薦,后面會(huì)解釋原因 * @return Api 返回一個(gè)具體實(shí)現(xiàn) * @throws */ @Deprecated public static Api createApi1() { return new Impl(); } }
使用配置文件的寫法好處在于,可以更加便捷的更改具體實(shí)現(xiàn)類,無(wú)須修改代碼,使得耦合性降低。
四、總結(jié)
何時(shí)選用簡(jiǎn)單工廠
如果想要完全封裝隔離具體實(shí)現(xiàn),讓外部只能通過(guò)接口來(lái)操作封裝體。想要把對(duì)外創(chuàng)建對(duì)象的職責(zé)集中管理和控制,因?yàn)楹?jiǎn)單工廠也稱萬(wàn)能工廠,可以創(chuàng)建很多的,不相關(guān)的對(duì)象。
到此這篇關(guān)于Java設(shè)計(jì)模式中的簡(jiǎn)單工廠模式解析的文章就介紹到這了,更多相關(guān)java簡(jiǎn)單工廠模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)ModbusCRC16校驗(yàn)的示例代碼
本文介紹了使用Java實(shí)現(xiàn)ModbusCRC16校驗(yàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-11-11詳解Java實(shí)現(xiàn)設(shè)計(jì)模式之責(zé)任鏈模式
責(zé)任鏈模式是一種行為設(shè)計(jì)模式,允許你將請(qǐng)求沿著處理鏈發(fā)送,然后處理者都可對(duì)其進(jìn)行處理,完成后可以再將其傳遞給下一個(gè)處理者。下面將會(huì)舉例說(shuō)明什么是責(zé)任鏈模式,責(zé)任鏈模式該如何使用2021-06-06Java 如何從list中刪除符合條件的數(shù)據(jù)
這篇文章主要介紹了Java 如何從list中刪除符合條件的數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11logback-spring.xml的內(nèi)容格式詳解
這篇文章主要介紹了logback-spring.xml的內(nèi)容格式詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的的朋友參考下吧2023-11-11解決springboot啟動(dòng)報(bào)錯(cuò)bean找不到的問題
這篇文章主要介紹了解決springboot啟動(dòng)報(bào)錯(cuò)bean找不到原因,本文給大家分享完美解決方案,通過(guò)圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03SpringMVC @RequestBody出現(xiàn)400 Bad Request的解決
這篇文章主要介紹了SpringMVC @RequestBody出現(xiàn)400 Bad Request的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04