java 工厂模式的写法_设计模式-工厂模式
一、概述
什么是工廠模式?
工廠模式(Factory Pattern)是最常見的一種設計模式之一。它主要是提供一種創建對象的最佳方法!
為什么要學習工廠模式?
與通過new來創建對象不同,使用工廠模式創建對象不會對客戶端暴露創建邏輯,并且是通過統一個共同的接口指向新創建的對象。同事工廠模式能將創建對象的代碼集中在一個對象或者方法中,可以避免代碼中的重復,并且更方便維護。面向接口編程,這樣的代碼更具有彈性,可以應對未來的擴展。
二、認識工廠模式
案例:假設你有一個Pizza店,每天要做出不同口味的Pizza。
假設我們有兩種口味Pizza
/*
* 抽象的Pizza類,Pizza制作一般包括準備,烘烤,切塊,包裝。
*/
public abstract class Pizza{
// Pizza名稱
protected String name;
// 面團類型
protected String dough;
// 醬料
protected String sauce;
// 芝士
protected String cheese;
// 蛤蜊
protected String clam;
// 佐料
protected List toppings = new ArrayList();
// 準備
public void prepare() {
System.out.print("準備食材,添加調料:");
for (int i = 0; i < toppings.size(); i++) {
System.out.print(toppings.get(i)+" ");
}
};
// 烘烤
public void bake() {
System.out.println("烘烤20分鐘...");
};
// 切塊
public void cut() {
System.out.println("切成x塊...");
};
// 包裝
public void box() {
System.out.println("包裝...");
}
// setter 和 getter方法省略
}
芝加哥風味的芝士Pizza
public class ChicagoStyleCheesePizza extends Pizza{
public ChicagoStyleCheesePizza() {
name = "Chicago Style Deep Dish Cheese Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.add("Shredded Mozzarella Cheese");
}
public void cut() {
System.out.println("Cut the pizza into square slices");
}
}
紐約風味的蔬菜Pizza
public class NyStyleVeggiePizza extends Pizza{
public NyStyleVeggiePizza() {
name = "NY style Sauce and Veggie Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.add("Grated Reggiano Veggie");
}
}
紐約風味的芝士Pizza
public class NyStyleCheesePizza extends Pizza{
public NyStyleCheesePizza() {
name = "NY style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.add("Grated Reggiano Cheese");
}
}
通過new創建對象
// 創建一個紐約風味的芝士Pizza
NyStyleCheesePizza nyPizza = new NyStyleCheesePizza();
當使用new得到一個對象時,確實得到了一個具體類,是針對具體類實現,而不是接口。代碼綁定具體類會導致代碼脆弱,更缺乏彈性。
簡單工廠
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("NyStyleCheesePizza")) {
return new NyStyleChieesePizza();
} else if(type.endsWith("ChicagoStyleCheesePizza")) {
return new ChicagoStyleCheesePizza();
}else {
return null;
}
}
}
// 創建簡單工廠對象
SimplePizzaFactory pizzaFactory = new SimplePizzaFactory();
// 創建Pizza對象
NyStyleChieesePizza myPizza = pizzaFactory.createPizza("NYStyleChieesePizza");
簡單工廠將對象的創建過程進行了封裝,用戶不需要知道具體的創建過程,只需要調用工廠類獲取對象即可。
這種簡單工廠的寫法是通過if else來判斷對象創建過程的。簡單工廠只是把new對象的問題轉移到另一個類中在實際使用過程中,違背了 開放-關閉原則,當然有些情況下可以通過反射調用來彌補這種不足。
工廠方法模式
定義:定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法讓類把實例化推遲到子類。
// 抽象的Pizza工廠
public abstract class PizzaFactory {
public Pizza getPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String pizza);
}
// 紐約Pizza工廠(芝加哥pizza工廠跟這個類似)
public class NYPizzaFactory extends PizzaFactory {
protected Pizza createPizza(String type) {
if (type.equals("NyStyleChieesePizza")) {
return new NyStyleCheesePizza();
} else if (type.equals("NyStyleVeggiePizza")) {
return new NyStyleVeggiePizza();
}else {
return null;
}
}
}
通過工廠方法創建對象
PizzaFactory pizzaFactory = new NYPizzaFactory();
// 創建一個蔬菜披薩
Pizza pizza = pizzaFactory.createPizza("NyStyleVeggiePizza");
當使用工廠方法創建對象時,是在編寫具體工廠類時決定創建的對象時哪一個,選擇使用哪個工廠類,自然就決定了十幾創建的是哪個對象。盡管只有一個具體工廠,工廠方法還是非常有用的!因為它將對象從“實現”從“使用”中解耦,如果增加對象或者改變對象,工廠是不會受到影響的!
抽象工廠模式
定義:提供一個接口,用于創建相關或依賴對象的家族,而不需要明確指定具體類。
抽象原料工廠
// 為了簡化, 這里的原料用字符串表示,其實每個原料應該用一個類表示
public interface PizzaIngredientFactory {
public String createDough();
public String createSauce();
public String createChieese();
public String[] createVeggies();
public String createPepperoni();
}
芝士pizza原料工廠
public class CheesePizzaIngredientFactory implements PizzaIngredientFactory {
public String createDough() {
return "薄地殼比薩生面團";
}
public String createSauce() {
return "紐約專用蘸料";
}
public String createChieese() {
return "Reggiano干酪";
}
public String[] createVeggies() {
return new String[]{"洋蔥","生菜","香菇"};
}
public String createPepperoni() {
return "意大利辣香腸";
}
}
創建pizza工廠
public class ChinaPizzaFactory extends PizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory = new ChinaPizzaIngredientFactory();
if(type.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
pizza.setName("中國芝士pizza");
}else if (type.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("中國蛤蜊pizza");
}
return pizza;
}
}
// 具體的Pizza類
public class ClamPizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public ClamPizza(PizzaIngredientFactory pizzaIngredientFactory) {
this.ingredientFactory = pizzaIngredientFactory;
}
public void prepare() {
System.out.println("Preparinging" + name);
// 根據pizza本身的特點,從工廠中獲取自己需要的原料
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
clam = ingredientFactory.creatClam();
}
}
創建一個中國蛤蜊pizza
// 創建一個Pizza工廠
PizzaFactory pizzaFactory = new ChinaPizzaFactory();
Pizza clamPizza = pizzaFactory.createPizza("clam");
抽象工廠模式將'對象' 與 ‘’組成對象或者對象依賴的類‘’解耦。
三、對比與分析
通過new來創建對象是面向具體類編程,擴展性差!
簡單工廠把全部的事情都在一個地方處理完了,但是當有新增或者修改的對象類時,很難進行擴展,違反了開閉原則。簡單工廠并不能算是工廠模式,而是一種編程習慣,或者是一種方法的封裝,并不具備彈性。
工廠方法是創建一個框架,讓子類決定如何實現。雖然可能導致類會變多,代碼稍微復雜,但是這樣做最大的好處是更具有彈性。
工廠模式的好處:將創建對象的代碼集中在一個對象或者方法中,可以避免代碼中重復的代碼,并且方便以后的維護。依賴接口,而不是具體的類。
如何選擇?
當需要將對象家族和具體的對象集合結合起來時,可以使用抽象工廠。
當需要將客戶代碼從需要實例化的具體類中解耦,或者目前還不中知道將來實例化哪些具體類時,可以使用工廠方法。
總結
以上是生活随笔為你收集整理的java 工厂模式的写法_设计模式-工厂模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 崴过一次脚,以后就更容易崴脚了:也包括这
- 下一篇: 以前,理光直接把 GR 相机的镜头拆下来