標籤:xtend auto 角色 統一 abstract runtime 問題 抽象 廠商
Factory 方法模式
返回設計模式目錄
閱讀目錄:
前言:
《大話設計模式》裡有一小節叫‘活字印刷,物件導向‘的,講了一個小故事,大意如下:
話說三國時期,曹操帶領大軍駐紮於赤壁。軍船相連,氣勢恢宏,眼看要滅掉東吳,統一天下,曹操甚悅,於是大宴群臣。席間曹操詩興大發,不覺吟道:"喝酒唱歌,人生真爽。……"。眾文武齊呼:"丞相好詩!"。於是一臣子速命印刷工匠刻板印刷,以便流傳天下。
樣章出來曹操一看,感覺不妥,道:"喝與唱此話過俗,應該為‘對酒當歌‘較好!",於是此臣就命工匠重新來過,此工匠連夜之功就此白費,只得重刻之。
樣章再次出來請曹操過目,曹操細細一品,覺得還是不好,說:"人生真爽太過直接,應改問語才夠意境,就改為‘對酒當歌人生幾何?……‘吧"。當臣子轉告工匠時,工匠暈倒。。。
這裡的問題是三國時期活字印刷還未發明,所以改字的時候,就必須整塊板全部重刻!如果有了活字印刷,則只需更改四個字即可,其餘工作均未白做。
第一,要改只需更改要改之字,此為可維護;第二,這些字並非這次用完就無用,完全可以在後來的印刷中重複使用,此乃可複用;第三此詩若要加字,只需另刻字加入即可,這是可擴充;第四字的排列其實可能豎排可能橫排,此時只需將活字移動即可滿足排列需求,此是靈活性好。編寫代碼時多考慮封裝,繼承,多態把程式的耦合度降低,使用物件導向思想使得程式更加的靈活,容易修改,並且易於複用。
好了,說了這麼多,相信大家對設計模式多少有點感覺了。不錯,設計模式就是為了讓我們的代碼更靈活,易擴充,好維護和能複用。現在我們就先從原廠模式總結吧!
一、簡單原廠模式
1.介紹
總結原廠模式之前先得說說簡單原廠模式。簡單原廠模式(又名靜態Factory 方法),不屬於GOF的23種設計模式之一。這種模式將建立對象的責任交由一個工廠對象,該工廠對象提供靜態公有方法向外提供產生對象的服務,所有產生對象的邏輯均包含在該靜態方法裡,對外不可見。簡單工廠是原廠模式裡最好理解的模式了,可以將其看作所有原廠模式的基礎。
2.UML類圖
假裝這裡有類圖
3.參考代碼
//這是用戶端,public class Client {public static void main(String[] args) {// 用戶端只需要傳入需要的產品類型,就能得到對應的產品,使用者不需要知道建立產品的細節Product product = SimpleFactory.create("A");// Product product = SimpleFactory.create("B");// 調用產生產品的顯示價格方法product.showPrice();}}/** * 抽象產品角色 * * @author ICE_melt * */interface Product {// 顯示產品價格public void showPrice();}// 具體產品Aclass ConcreateProductA implements Product {@Overridepublic void showPrice() {System.out.println("這是A產品,價格為10RMB,很便宜");}}// 具體產品Bclass ConcreateProductB implements Product {@Overridepublic void showPrice() {System.out.println("這是B產品,價格為600RMB,很貴的");}}/** * 工廠角色(即普通類提供了建立其他類的方法) * * @author ICE_melt * */class SimpleFactory {/** * 簡單工廠一般為靜態方法,其內包含必要的邏輯判斷,能夠根據用戶端的條件建立具體的產品對象 * <br><b>剖析:</b> * <br>現在的產品都是基於<code>Product<code>介面的子類,如果增加產品,繼承體系沒有問題 * <br>但是工廠產生邏輯需要修改(增加if分支判斷邏輯),這一點違背了“開放封閉原則” */public static Product create(String type) {if ("A".equals(type)) {return new ConcreateProductA();} else if ("B".equals(type)) {return new ConcreateProductB();} else {new RuntimeException(type + "產品類型暫時不能生產,請聯絡生產廠商!");}return null;}}
4.總結
簡單原廠模式的優點是分離了產品的建立者和使用者,有利於軟體系統結構的最佳化。局限是有需求變動時不修改代碼的話是不能夠擴充的。
返回頂部
二、Factory 方法模式
1.介紹
Factory 方法模式,又叫做多態性工廠。該模式定義一個用於建立對象的介面,讓子類決定執行個體化那一個產品對象。Factory 方法使一個類的執行個體化延遲到其子類。
2.UML類圖
假裝有類圖
3.參考代碼
首先是抽象產品類:
/** * 產品抽象 * * @author ICE_melt * */public abstract class AbstractProduct {public AbstractProduct() {}// 所有產品都有對外展示的方法public abstract void display();}
基礎抽象產品類的三種產品:
//產品--汽車public class CarProduct extends AbstractProduct {@Overridepublic void display() {System.out.println("我有四個輪子,在陸地上跑的飛快");}}
//產品--飛機public class AirplaneProduct extends AbstractProduct {@Overridepublic void display() {System.out.println("我有兩個機翼,能在天上飛");}}
//產品--輪船public class ShipProduct extends AbstractProduct {@Overridepublic void display() {System.out.println("我在海裡,速度很快");}}
然後是工廠介面:
/** * 一個工廠介面,負責定義產品對象的生產 * (工廠介面也可以用抽象方法實現) * @author ICE_melt * */public interface IFactory {/* * * 建立一個產品對象 */public AbstractProduct produceProduct();}
工廠介面的三個具體工廠,每個工廠負責生產一種產品:
//汽車工廠,生產汽車public class CarFactory implements IFactory {@Overridepublic AbstractProduct produceProduct() {return new CarProduct();}}
//飛機工廠,生產飛機public class AirplaneFactory implements IFactory {@Overridepublic AbstractProduct produceProduct() {return new AirplaneProduct();}}
//輪船工廠,生產輪船public class ShipFactory implements IFactory {@Overridepublic AbstractProduct produceProduct() {return new ShipProduct();}}
用戶端代碼:
/** * 用戶端代碼 * @author ICE_melt * */public class Client {public static void main(String[] args) {//這裡可以將工廠類的全路徑類名寫到項目的設定檔裡,並添加一個讀取該配置的方法String factoryConfig = readConfig();IFactory factory;try {//用戶端代碼只與抽象工廠 和 抽象產品 這兩個頂級介面耦合,//後台增加 一種新的產品的話,只需要同時增加 該產品的工廠類,//不需要修改任何已存在的代碼factory = (IFactory)Class.forName(factoryConfig).newInstance();AbstractProduct product = factory.produceProduct();product.display();} catch (Exception e) {//異常處理e.printStackTrace();}}public static String readConfig(){//可以將工廠類名全路徑寫到設定檔裡,這樣用戶端無需//更改代碼,只需配置即可完成不用產品的的展示需求return "com.icemelt.designpattern.factorymethod.AirplaneFactory";}}
4.總結
Factory 方法首先需要屏蔽產品類的具體實現,產品類如何變化,調用者都不需要關心,只需關心產品類的介面,通常介面是相對穩定,只要此介面不發生變化,那麼系統上層就不會發生變化(這也是面向介面編程的好處)。其次需要屏蔽Factory 方法的具體實現,道理同前。然後我們就能享受Factory 方法給代碼帶來的靈活性的好處:此時所有用戶端代碼只與兩個抽象類別(或介面)有關,增加產品只需完成該產品和對應Factory 方法的編碼工作即可完成需求增加(不需要修改用戶端代碼和後台已存在的代碼,客戶需要新增功能只需修改配置即可)
通常實際應用中商務邏輯會比較複雜,產品類可能並沒有統一的介面(也有可能是曆史遺留原因),這時候需要想辦法加上一層統一的間接關係後才能繼續應用本模式。
返回頂部
java設計模式:Factory 方法模式(Factory Method)