工廠模式有三種:簡單工廠模式、工廠方法模式、抽象工廠模式。
這裏以製造coffee的例子開始工廠模式設計之旅。我們知道coffee只是一種泛舉,在點購咖啡時需要指定具體的咖啡種類:美式咖啡、卡布奇諾、拿鐵等等。
接口獲取coffee
public abstract class Coffee {
public abstract String getName();
}
不同咖啡的創建
// 美式咖啡
public class Americano extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
}
//卡布奇諾
public class Cappuccino extends Coffee {
@Override
public String getName() {
return "卡布奇諾";
}
}
// 拿鐵
public class Latte extends Coffee {
@Override
public String getName() {
return "拿鐵";
}
}
一、簡單工廠模式
public class SimpleFactory {
/**
* 通過類型獲取Coffee實例對象
*/
public static Coffee createInstance(String type){
if("americano".equals(type)){
return new Americano();
}else if("cappuccino".equals(type)){
return new Cappuccino();
}else if("latte".equals(type)){
return new Latte();
}else{
throw new RuntimeException("type["+type+"]類型不可識別,沒有匹配到可實例化的對象!");
}
}
public static void main(String[] args) {
Coffee latte = SimpleFactory.createInstance("latte");
System.out.println("創建的咖啡實例爲:" + latte.getName());
}
}
特點
1、它是一個具體的類,非接口抽象類。有一個重要的create()方法,利用 if 或者 switch 創建產品並返回。create()方法通常是靜態的,所以也稱之爲靜態工廠。
2、擴展性差(我想增加一種麪條,除了新增一個麪條產品類,還需要修改工廠類方法)。
二、工廠方法模式
定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個,工廠方法讓類把實例化推遲到了子類。
場景延伸:不同地區咖啡工廠受制於環境、原料等因素的影響,製造出的咖啡種類有限。中國咖啡工廠僅能製造卡布奇諾、拿鐵,而美國咖啡工廠僅能製造美式咖啡、拿鐵。
定義一個抽象的咖啡工廠
public abstract class CoffeeFactory {
/**
* 生產可製造的咖啡
* @return
*/
public abstract Coffee[] createCoffee();
}
子類實現工廠方法
子類實現工廠方法
/**
* 中國咖啡工廠,製造卡布奇諾和拿鐵
*/
public class ChinaCoffeeFactory extends CoffeeFactory {
@Override
public Coffee[] createCoffee() {
return new Coffee[]{new Cappuccino(), new Latte()};
}
}
/**
* 美國咖啡工廠,製造美式咖啡和拿鐵
*/
public class AmericaCoffeeFactory extends CoffeeFactory {
@Override
public Coffee[] createCoffee() {
return new Coffee[]{new Americano(), new Latte()};
}
}
測試類
public class FactoryMethodTest {
private static void print(Coffee[] c){
for (Coffee coffee : c) {
System.out.println(coffee.getName());
}
}
public static void main(String[] args) {
CoffeeFactory chinaCoffeeFactory = new ChinaCoffeeFactory();
Coffee[] chinaCoffees = chinaCoffeeFactory.createCoffee();
System.out.println("中國咖啡工廠可以生產的咖啡有:");
print(chinaCoffees);
CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();
Coffee[] americaCoffees = americaCoffeeFactory.createCoffee();
System.out.println("美國咖啡工廠可以生產的咖啡有:");
print(americaCoffees);
}
}
輸出:
中國咖啡工廠可以生產的咖啡有:
卡布奇諾
拿鐵
美國咖啡工廠可以生產的咖啡有:
美式咖啡
拿鐵
特點
1、相比簡單工廠方法,增加了一個抽象類(或者接口),由不同的產品工廠去實現該接口;
1、可以一定程度增加擴展性,若增加一個產品實現,只需要實現產品接口,修改工廠創建產品的方法,消費者可以無感知(若消費者不關心具體產品是什麼的情況);
2、可以一定程度增加代碼的封裝性、可讀性。清楚的代碼結構,對於消費者來說很少的代碼量就可以完成很多工作;
適用場景
1、消費者不關心它所要創建對象的類(產品類)的時候。
2、消費者知道它所要創建對象的類(產品類),但不關心如何創建的時候。
三、抽象工廠模式
提供一個接口,用於創建相關或依賴對象的家族,而不需要明確指定具體類。
在上述的場景上繼續延伸:咖啡工廠做大做強,引入了新的飲品種類:茶、 碳酸飲料。中國工廠只能製造咖啡和茶,美國工廠只能製造咖啡和碳酸飲料。如果用上述工廠方法方式,除去對應的產品實體類還需要新增2個抽象工廠(茶製造工廠、碳酸飲料製造工廠),4個具體工廠實現。隨着產品的增多,會導致類爆炸。所以這裏引出一個概念產品家族,在此例子中,不同的飲品就組成我們的飲品家族, 飲品家族開始承擔創建者的責任,負責製造不同的產品。
抽象的飲料產品家族製造工廠
public interface AbstractDrinksFactory {
/**
* 製造咖啡
*/
Coffee createCoffee();
/**
* 製造茶
*/
Tea createTea();
/**
* 製造碳酸飲料
*/
Sodas createSodas();
}
中國飲品工廠,製造咖啡與茶
public class ChinaDrinksFactory implements AbstractDrinksFactory {
@Override
public Coffee createCoffee() {
return new Latte();
}
@Override
public Tea createTea() {
return new MilkTea();
}
@Override
public Sodas createSodas() {
return null;
}
}
美國飲品製造工廠,製造咖啡和碳酸飲料
public class AmericaDrinksFactory implements AbstractDrinksFactory {
@Override
public Coffee createCoffee() {
return new Latte();
}
@Override
public Tea createTea() {
return null;
}
@Override
public Sodas createSodas() {
return new CocaCola();
}
}
抽象工廠模式與工廠方法模式的區別:
抽象工廠模式是工廠方法模式的升級版本,他用來創建一組相關或者相互依賴的對象。他與工廠方法模式的區別就在於,工廠方法模式針對的是一個產品等級結構;而抽象工廠模式則是針對的多個產品等級結構。在編程中,通常一個產品結構,表現爲一個接口或者抽象類,也就是說,工廠方法模式提供的所有產品都是衍生自同一個接口或抽象類,而抽象工廠模式所提供的產品則是衍生自不同的接口或抽象類。
抽象工廠模式的優點:
抽象工廠模式除了具有工廠方法模式的優點外,最主要的優點就是可以在類的內部對產品族進行約束。所謂的產品族,一般或多或少的都存在一定的關聯,抽象工廠模式就可以在類內部對產品族的關聯關係進行定義和描述,而不必專門引入一個新的類來進行管理。
抽象工廠模式的缺點:
產品族的擴展將是一件十分費力的事情,假如產品族中需要增加一個新的產品,則幾乎所有的工廠類都需要進行修改。所以使用抽象工廠模式時,對產品等級結構的劃分是非常重要的。
適用場景:
當需要創建的對象是一系列相互關聯或相互依賴的產品族時,便可以使用抽象工廠模式。說的更明白一點,就是一個繼承體系中,如果存在着多個等級結構(即存在着多個抽象類),並且分屬各個等級結構中的實現類之間存在着一定的關聯或者約束,就可以使用抽象工廠模式。假如各個等級結構中的實現類之間不存在關聯或約束,則使用多個獨立的工廠來對產品進行創建,則更合適一點。
四、總結
1、簡單工廠:不能算是真正意義上的設計模式,但可以將客戶程序從具體類解耦,簡單方便易上手;
2、工廠方法:使用繼承,把對象的創建委託給子類,由子類來實現創建方法,可以看作是抽象工廠模式中只有單一產品的情況;
3、抽象工廠:使對象的創建被實現在工廠接口所暴露出來的方法中;
4、無論是簡單工廠模式,工廠方法模式,還是抽象工廠模式,他們都屬於工廠模式,在形式和特點上也是極爲相似的,他們的最終目的都是爲了解耦。在使用時,我們不必去在意這個模式到底工廠方法模式還是抽象工廠模式,因爲他們之間的演變常常是令人琢磨不透的。經常你會發現,明明使用的工廠方法模式,當新需求來臨,稍加修改,加入了一個新方法後,由於類中的產品構成了不同等級結構中的產品族,它就變成抽象工廠模式了;而對於抽象工廠模式,當減少一個方法使的提供的產品不再構成產品族之後,它就演變成了工廠方法模式。
參考:https://www.cnblogs.com/carryjack/p/7709861.html