工廠方法模式:是23中基本設計模式之一,它定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法讓類的實例化延遲到了子類。
注: 這裏所謂的 “決定” 並不是指模式允許子類本身在運行時做決定,而是在編寫創建者類時,不需要知道實際創建的產品是哪一個,選擇了使用哪個子類,就等於決定了創建的產品是什麼了。
工廠方法模式的四要素:
- 創建者。
- 創建者實現。
- 產品。
- 產品實現。
來看一下它的類圖:
下面我們通過實例來強化學習一下:
我們以去專賣店買筆記本做了例子,這裏的產品肯定就是筆記本了,因爲筆記本的種類很多,所以我們定義一個筆記本的抽象基類,這樣可以統一產品的引用類,與具體的實現類隔離開來。
如果現在只考慮去一家專賣店(代號:A)買筆記本,可以運用上一篇 簡單工廠模式 實現,通過工廠返回這個專賣店所有的電腦型號。
- 定義一個抽象的產品類 Laptop (筆記本電腦);
- 實現兩個繼承 Laptop 的具體筆記本電腦:A1Laptop、A2Laptop;
- 通過一個工廠 ALaptopFactory 根據類型名返回不同的筆記本的具體實現;
但是實際生活中,有很多不同的專賣店,每家專賣店買的電腦品牌也大有不同,這裏我們就可以運用到工廠方法模式。有了不同專賣店的概念,每家專賣店都有自己的品牌及其系列電腦。這裏我們將專賣店作爲超類,讓不同品牌的專賣店都繼承它,但是由每個品牌的專賣店決定提供什麼型號的電腦。
- 將筆記版專賣店定義一個抽象的類 LaptopStore;
- 讓 ALaptopFactory 繼承 LaptopStore;
- 擴展一個新的專賣店(代號:B) BLaptopFactory(它對應的產品爲 B1Laptop、B2Laptop);
此時我們就利用了工廠模式設計實現了我們的需求。具體代碼如下:
抽象專賣店類:
package com.dz.demo.pattern.factorypattern.factory;
import com.dz.demo.pattern.factorypattern.product.Laptop;
/**
* Created by dzwang on 2019/3/25.
*/
public abstract class LaptopStore {
public Laptop buyLaptop(String type) {
Laptop laptop = chooseLaptop(type);
System.out.println("I want to buy " + type);
laptop.information();
return laptop;
}
abstract Laptop chooseLaptop(String type);
}
繼承於它的兩個實現類:
// A專賣店
public class ALaptopFactory extends LaptopStore {
Laptop chooseLaptop(String type) {
Laptop laptop = null;
if (type.equals("A1")) {
laptop = new A1Laptop();
} else if (type.equals("A2")) {
laptop = new A2Laptop();
}
return laptop;
}
}
// B專賣店
public class BLaptopFactory extends LaptopStore {
Laptop chooseLaptop(String type) {
Laptop laptop = null;
if (type.equals("B1")) {
laptop = new B1Laptop();
} else if (type.equals("B2")) {
laptop = new B2Laptop();
}
return laptop;
}
}
定義抽象的產品基類:
public abstract class Laptop {
public abstract void information();
}
具體的產品類:
// A專賣店 A1型號筆記本
public class A1Laptop extends Laptop {
public void information(){
System.out.println("name:A1");
System.out.println("price:¥5000");
}
}
// A專賣店 A2型號筆記本
public class A2Laptop extends Laptop{
public void information(){
System.out.println("name:A2");
System.out.println("price:¥8000");
}
}
// B專賣店 B1型號筆記本
public class B1Laptop extends Laptop{
public void information(){
System.out.println("name:B1");
System.out.println("price:¥6000");
}
}
// B專賣店 B2型號筆記本
public class B2Laptop extends Laptop {
public void information() {
System.out.println("name:B2");
System.out.println("price:¥9000");
}
}
具體測試如下:
public class FactoryDemo {
public static void main(String[] args) {
/**
* Customer 1 want to buy A1
*/
LaptopStore laptopStore = new ALaptopFactory();
laptopStore.buyLaptop("A1");
/**
* Customer 2 want to buy B2
*/
laptopStore = new BLaptopFactory();
laptopStore.buyLaptop("B2");
}
}
// 運行結果如下:
// I want to buy A1
// name:A1
// price:¥5000
// I want to buy B2
// name:B2
// price:¥9000
工廠方法模式中具體類的實現和簡單工廠模式其實很類似,不同的是工廠方法模式中的具體類擴展自一個類。
- 工廠方法模式創建的是一個框架,讓子類決定如何去實現。
- 簡單工廠是將對象的創建進行封裝。
我們從中可以學習到:
- 將創建對象的代碼進行封裝,集中在一個類中或者方法中,可以有效的管理代碼,方便後期維護和擴展。
- 在這裏我們是針對接口的編程,而不是針對實現編程,其實也就是設計模式六大原則中的(依賴倒置原則)。