02.工廠設計模式
阿新 • • 發佈:2022-12-10
簡單工廠模式(靜態工廠模式)
-
簡單工廠模式是屬於建立型模式,是工廠模式的的一種,簡單工廠模式是有一個工廠物件決定創建出那一種產品類的例項。簡單工廠模式是工廠模式家族的最簡單實用的模式。
-
簡單工廠模式:定義一個建立物件的類,由這個類來建立例項化物件的行為(程式碼)
-
在軟體開發當中,當我們會用到大量的建立某種、某類或者某批物件時,就會使用工廠模式。
-
程式碼示例:
/** * @author 通過程式看世界 * @version 1.0 * 將Pizza做成抽象類 */ public abstract class Pizza { protected String name; //披薩的名字 //準備原材料,不同的披薩不一樣,因此.我們做成抽象方法 public abstract void prepare(); public void bake() { System.out.println(name + "backing"); } public void cut() { System.out.println(name + "cutting"); } //打包 public void box() { System.out.println(name + "boxing"); } public void setName(String name) { this.name = name; } }
/** * @author 通過程式看世界 * @version 1.0 * 乳酪披薩 */ public class CheesePizza extends Pizza { @Override public void prepare() { System.out.println("給製作乳酪披薩準備原材料"); } }
/** * @author 通過程式看世界 * @version 1.0 * 希臘披薩 */ public class GreekPizza extends Pizza{ @Override public void prepare() { System.out.println("給希臘披薩準備原材料"); } }
/** * @author 通過程式看世界 * @version 1.0 * 簡單工廠類 */ public class SimpleFactor { //根據orderType返回對應的Pizza物件 public Pizza createPizza(String type) { System.out.println("使用簡單工廠模式"); Pizza pizza = null; if (type.equals("greek")){ pizza = new CheesePizza(); pizza.setName("希臘披薩"); }else if (type.equals("cheese")){ pizza = new CheesePizza(); pizza.setName("乳酪披薩"); } return pizza; } }
/** * @author 通過程式看世界 * @version 1.0 * 訂購披薩的類 */ public class OrderPizza { //定義一個一個簡單工廠物件 SimpleFactor simpleFactor; Pizza pizza; public OrderPizza(SimpleFactor simpleFactor) { setSimpleFactor(simpleFactor); } public void setSimpleFactor(SimpleFactor simpleFactor) { String type = ""; //使用者輸入 this.simpleFactor = simpleFactor; //設定簡單工廠物件 do { type = getType(); pizza = this.simpleFactor.createPizza(type); //輸出pizza if (pizza != null) { pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } else { System.out.println("訂購pizza失敗!"); break; } } while (true); } //寫一個方法,可以獲取客戶希望訂購的Pizza種類 private String getType() { try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("input pizza type:"); String str = bufferedReader.readLine(); return str; } catch (IOException e) { e.printStackTrace(); } return ""; } }
/** * @author 通過程式看世界 * @version 1.0 * 相當於一個客戶端 */ public class PizzaStore { public static void main(String[] args) { new OrderPizza(new SimpleFactor()); System.out.println("退出程式"); } }
-
程式執行結果
input pizza type: cheese 使用簡單工廠模式 給製作乳酪披薩準備原材料 乳酪披薩backing 乳酪披薩cutting 乳酪披薩boxing input pizza type: greek 使用簡單工廠模式 給製作乳酪披薩準備原材料 希臘披薩backing 希臘披薩cutting 希臘披薩boxing input pizza type:
-
程式碼分析
- 後期我們需要增加新的披薩型別,只需要在建立一個披薩類,在工廠類當中做出if判斷處理即可
工廠方式模式
-
定義一個建立物件的抽象方法,由子類決定要例項化的類,工廠方法模式將物件的例項化推遲到子類。
-
需求:客戶在點披薩的時候,可以點不同口味的披薩。比如:北京的乳酪pizza、北京的胡椒pizza、或者倫敦的乳酪pizza、倫敦的胡椒pizza
-
程式碼例項:
package com.db.factormethod.pizza; /** * @author 通過程式看世界 * @version 1.0 * 將Pizza做成抽象類 */ public abstract class Pizza { protected String name; //準備 //準備原材料,不同的披薩不一樣,因此.我們做成抽象方法 public abstract void prepare(); public void bake() { System.out.println(name + "backing"); } public void cut() { System.out.println(name + "cutting"); } //打包 public void box() { System.out.println(name + "boxing"); } public void setName(String name) { this.name = name; } }
package com.db.factormethod.pizza; /** * @author 通過程式看世界 * @version 1.0 * 倫敦的胡椒披薩 */ public class LDPepperPizza extends Pizza{ @Override public void prepare() { setName("倫敦的胡椒披薩"); System.out.println("為倫敦的胡椒披薩準備原材料"); } }
package com.db.factormethod.pizza; /** * @author 通過程式看世界 * @version 1.0 * 倫敦的胡椒披薩 */ public class LDCheesePizza extends Pizza{ @Override public void prepare() { setName("倫敦的胡椒披薩"); System.out.println("為倫敦的胡椒披薩準備原材料"); } }
package com.db.factormethod.pizza; /** * @author 通過程式看世界 * @version 1.0 */ public class BJPepperPizza extends Pizza{ @Override public void prepare() { setName("北京的胡椒披薩"); System.out.println("為北京的胡椒披薩準備原材料"); } }
package com.db.factormethod.pizza; /** * @author 通過程式看世界 * @version 1.0 */ public class BJCheesePizza extends Pizza{ @Override public void prepare() { setName("北京乳酪披薩"); System.out.println("為北京的乳酪pizza準備原材料"); } }
package com.db.factormethod.order; import com.db.factor.order.SimpleFactor; import com.db.factormethod.pizza.Pizza; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @author 通過程式看世界 * @version 1.0 * 訂購披薩的類 */ public abstract class OrderPizza { public OrderPizza() { Pizza pizza = null; String type; //訂購披薩的型別 do { type = getType(); pizza = createPizza(type); //輸出Pizza的製作過程 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.bake(); } while (true); } //定義一個抽象方法,createPizza,讓各個工廠類自己去實現 public abstract Pizza createPizza(String type); //寫一個方法,可以獲取客戶希望訂購的Pizza種類 private String getType() { try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("input pizza type:"); String str = bufferedReader.readLine(); return str; } catch (IOException e) { e.printStackTrace(); } return ""; } }
package com.db.factormethod.order; import com.db.factormethod.pizza.LDCheesePizza; import com.db.factormethod.pizza.LDPepperPizza; import com.db.factormethod.pizza.Pizza; /** * @author 通過程式看世界 * @version 1.0 * 倫敦訂購披薩的類 */ public class LDOrderPizza extends OrderPizza { @Override public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new LDCheesePizza(); } else if (type.equals("pepper")) { pizza = new LDPepperPizza(); } return pizza; } }
package com.db.factormethod.order; import com.db.factormethod.pizza.BJCheesePizza; import com.db.factormethod.pizza.BJPepperPizza; import com.db.factormethod.pizza.Pizza; /** * @author 通過程式看世界 * @version 1.0 * 北京訂購披薩的類 */ public class BJOrderPizza extends OrderPizza{ @Override public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")){ pizza = new BJCheesePizza(); }else if (type.equals("pepper")){ pizza = new BJPepperPizza(); } return pizza; } }
package com.db.factormethod.order; /** * @author 通過程式看世界 * @version 1.0 */ public class PizzaStore { public static void main(String[] args) { new BJOrderPizza(); } }
-
執行結果
input pizza type:
cheese
為北京的乳酪pizza準備原材料
北京乳酪披薩backing
北京乳酪披薩cutting
北京乳酪披薩backing
input pizza type:
pepper
為北京的胡椒披薩準備原材料
北京的胡椒披薩backing
北京的胡椒披薩cutting
北京的胡椒披薩backing
抽象工廠模式
抽象工廠模式
-
抽象工廠模式,定義了一個interface用於建立相關或者有依賴關係的物件簇,而無需指明具體的類
-
抽象工廠模式可以將簡單工廠模式和工廠方法模式進行整合
-
從設計層面來看,抽象工廠模式就是對簡單工廠模式的改進(或者稱為進一步的抽象)
-
將工廠抽象成兩層,AbsFactory(抽象工廠)和具體實現的工廠子類,程式設計師可以根據建立物件型別使用相應的工廠子類。這樣將單個的簡單工廠類變成了工廠簇,更加有利於程式碼的維護和擴充套件
-
程式碼示例:
package com.db.absfactory.pizza; /** * @author 通過程式看世界 * @version 1.0 * 將Pizza做成抽象類 */ public abstract class Pizza { protected String name; //準備 //準備原材料,不同的披薩不一樣,因此.我們做成抽象方法 public abstract void prepare(); public void bake() { System.out.println(name + "backing"); } public void cut() { System.out.println(name + "cutting"); } //打包 public void box() { System.out.println(name + "boxing"); } public void setName(String name) { this.name = name; } }
package com.db.absfactory.pizza; /** * @author 通過程式看世界 * @version 1.0 * 倫敦的胡椒披薩 */ public class LDPepperPizza extends Pizza { @Override public void prepare() { setName("倫敦的胡椒披薩"); System.out.println("為倫敦的胡椒披薩準備原材料"); } }
package com.db.absfactory.pizza; /** * @author 通過程式看世界 * @version 1.0 * 倫敦的胡椒披薩 */ public class LDCheesePizza extends Pizza { @Override public void prepare() { setName("倫敦的胡椒披薩"); System.out.println("為倫敦的胡椒披薩準備原材料"); } }
package com.db.absfactory.pizza; /** * @author 通過程式看世界 * @version 1.0 */ public class BJPepperPizza extends Pizza { @Override public void prepare() { setName("北京的胡椒披薩"); System.out.println("為北京的胡椒披薩準備原材料"); } }
package com.db.absfactory.pizza; /** * @author 通過程式看世界 * @version 1.0 */ public class BJCheesePizza extends Pizza { @Override public void prepare() { setName("北京乳酪披薩"); System.out.println("為北京的乳酪pizza準備原材料"); } }
package com.db.absfactory.order; import com.db.absfactory.pizza.Pizza; /** * @author 通過程式看世界 * @version 1.0 * 抽象工廠模式的抽象層(介面) */ public interface IAbsFactory { //讓下面的工廠子類去具體實現 public Pizza createPizza(String type); }
package com.db.absfactory.order; import com.db.absfactory.pizza.BJCheesePizza; import com.db.absfactory.pizza.BJPepperPizza; import com.db.absfactory.pizza.Pizza; /** * @author 通過程式看世界 * @version 1.0 * 北京的工廠 */ public class BJFactor implements IAbsFactory { @Override public Pizza createPizza(String type) { System.out.println("使用抽象工廠模式"); Pizza pizza = null; if (type.equals("cheese")){ pizza = new BJCheesePizza(); }else if(type.equals("pepper")){ pizza = new BJPepperPizza(); } return pizza; } }
package com.db.absfactory.order; import com.db.absfactory.pizza.*; /** * @author 通過程式看世界 * @version 1.0 */ public class LDFactor implements IAbsFactory{ @Override public Pizza createPizza(String type) { System.out.println("使用抽象工廠模式"); Pizza pizza = null; if (type.equals("cheese")){ pizza = new LDCheesePizza(); }else if(type.equals("pepper")){ pizza = new LDPepperPizza(); } return pizza; } }
package com.db.absfactory.order; import com.db.absfactory.pizza.Pizza; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @author 通過程式看世界 * @version 1.0 * 訂購披薩的類 */ public class OrderPizza { IAbsFactory iAbsFactory; public OrderPizza(IAbsFactory iAbsFactory) { setiAbsFactory(iAbsFactory); } public void setiAbsFactory(IAbsFactory iAbsFactory) { this.iAbsFactory = iAbsFactory; String type = ""; Pizza pizza = null; do { type = getType(); pizza = iAbsFactory.createPizza(type); //輸出披薩的製作guoc if (pizza != null) { pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); }else { System.out.println("訂購失敗"); } } while (true); } //寫一個方法,可以獲取客戶希望訂購的Pizza種類 private String getType() { try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("input pizza type:"); String str = bufferedReader.readLine(); return str; } catch (IOException e) { e.printStackTrace(); } return ""; } }
package com.db.absfactory.order; import com.sun.org.apache.bcel.internal.generic.NEW; /** * @author 通過程式看世界 * @version 1.0 */ public class PizzaStore { public static void main(String[] args) { new OrderPizza(new BJFactor()); } }
-
執行結果
input pizza type: pepper 使用抽象工廠模式 為北京的胡椒披薩準備原材料 北京的胡椒披薩backing 北京的胡椒披薩cutting 北京的胡椒披薩boxing input pizza type: cheese 使用抽象工廠模式 為北京的乳酪pizza準備原材料 北京乳酪披薩backing 北京乳酪披薩cutting 北京乳酪披薩boxing
JDK當中的工廠模式
Calendar原始碼分析
Calendar類當中的createCalendar方法就是採用了簡單工廠模式,根據傳輸的不同的aLocale 返回不同的Calendar例項
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
return cal;
}
工廠模式的總結
- 工廠模式的意義
- 將例項化物件的程式碼提取出來,放到一個類當中進行統一管理和維護,達到和主專案的依賴關係的解耦合,從而提高專案的擴充套件性和維護性
- 三種工廠模式
- 簡單工廠模式
- 工廠方法模式
- 抽象工廠模式
- 設計模式的依賴抽象原則
- 建立物件例項的時候,不要直接new類,而是把這個new類的動作放到一個工廠的方法當中,並且返回,有的書上說,變數不要直接持有具體類的引用。
- 不要讓類繼承具體類,而是繼承抽象類或者實現介面
- 不要覆蓋基類中已經實現的方法