建立型設計模式之工廠方法模式
工廠方法模式的介紹
工廠方法模式是一種結構簡單的模式,並且在我們的應用中很廣泛,如Android中Activity的各個生命週期的回撥,以onCreate方法為例,它就可以看做是一個工廠方法,我們在其中構造我們的View並返回給framework處理。
工廠方法模式的定義
定義一個用於建立物件的介面,讓子類決定例項化哪個類。
工廠方法模式的使用場景
在任何需要生成複雜物件的地方,都可以使用工廠方法模式。複雜物件適合使用工廠方法模式,用new就能完成建立的物件無需使用工廠方法模式。
工廠方法模式的類圖
角色介紹:
Factory - 抽象工廠,是工廠方法的核心
ConcreteFactory - 具體工廠,實現了業務邏輯
Product - 抽象產品,是工廠方法模式所建立的產品的父類
ConcreteProduct - 為實現抽象產品的某個具體產品
抽象工廠的簡單實現
下面生產汽車為例,要生產三款汽車,於是使用一條生產線來生產,我們先定義產品,產品是汽車。
抽象汽車,即抽象產品
public abstract class Car {
public abstract void drive();
}
接下來是具體的車型
奧迪汽車,即具體的產品類
public class AudiCar extends Car { @Override public void drive() { System.out.println("奧迪汽車開始啟動啦!"); } }
賓士汽車,即具體的產品類
public class BenzCar extends Car {
@Override
public void drive() {
System.out.println("賓士車開始啟動啦!");
}
}
寶馬汽車,即具體的產品類
public class BWMCar extends Car {
@Override
public void drive() {
System.out.println("寶馬汽車開始啟動啦!");
}
}
有了產品就要有工廠來生產,定義一個汽車抽象工廠。
抽象汽車工廠,即抽象工廠角色
public abstract class CarFactory {
public abstract Car createCar();
}
接下來是具體的車型工廠。
生產奧迪車的工廠,即具體工廠類
public class AudiCarFactory extends CarFactory {
@Override
public Car createCar() {
return new AudiCar();
}
}
生產賓士車的工廠,即具體工廠類
public class BenzCarFactory extends CarFactory {
@Override
public Car createCar() {
return new BenzCar();
}
}
生產寶馬車的工廠,即具體工廠類
public class BWMCarFactory extends CarFactory {
@Override
public Car createCar() {
return new BWMCar();
}
}
最後我們將各個汽車的生產組裝成一條生產線。
客戶端
public class Client {
public static void main(String[] args){
//製造各個工廠
CarFactory audiFactory = new AudiCarFactory();
CarFactory benzFactory = new BenzCarFactory();
CarFactory bwmFactory = new BWMCarFactory();
//生產各種車
Car audiCar = audiFactory.createCar();
Car benzCar = benzFactory.createCar();
Car bwmCar = bwmFactory.createCar();
//車啟動
audiCar.drive();
benzCar.drive();
bwmCar.drive();
}
}
輸出結果
奧迪汽車開始啟動啦!
賓士車開始啟動啦!
寶馬汽車開始啟動啦!
可以看到我們需要哪種車型就可以定義哪種車型的具體工廠,像這樣擁有多個工廠的的方式我們稱之為多工廠模式,每個工廠各司其職。
但上面的方式不好的是會產生大量工廠,使程式碼臃腫,在實際開發中,我們可以使用反射的方式更加簡潔的來生產具體的產品物件,此時需要在工廠方法的引數列表中傳入一個Class類來決定是哪一個產品類。
使用反射的方式來生產具體的產品物件,抽象工廠角色
public abstract class CarFactory2 {
/**
* 抽象工廠方法,具體生產什麼產品由子類決定
*/
public abstract <T extends Car> T createCar(Class<T> car);
}
對於 具體的工廠,則通過反射獲取類的例項即可
public class ConcreteCarFactory extends CarFactory2 {
@Override
public <T extends Car> T createCar(Class<T> car) {
Car c = null;
try {
c = (T) Class.forName(car.getName()).newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) c;
}
}
客戶端
public class Client {
public static void main(String[] args){
//建立工廠
CarFactory2 carFactory = new ConcreteCarFactory2();
//生產車
AudiCar audiCar = carFactory.createCar(AudiCar.class);
BenzCar benzCar = carFactory.createCar(BenzCar.class);
BWMCar bwmCar = carFactory.createCar(BWMCar.class);
//車啟動
audiCar.drive();
benzCar.drive();
bwmCar.drive();
}
}
輸出和和上面一樣
以上的方式,需要哪一個產品的物件,就傳入哪一個產品的類的型即可,這種方式比較簡潔,動態。
上面我們有三個工廠,如果我們只需要生產一種車型,即我們只有一個工廠時,我們就可以把抽象工廠簡化掉,將對應的工廠方法改為靜態方法,像下面,我們只生產一輛五菱車。
一個工廠,只生產一種產品
public class Factory {
public static Car createWuLingCar(){
return new WuLingCar();
}
}
像這樣的方式又稱為簡單工廠方式或靜態工廠方式,它是工廠方式模式的一個弱化版本。
總結
工廠模式依賴於抽象的架構,將例項化的具體任務交給子類去完成,有非常好的擴充套件性。
優點:
將類的例項化邏輯交由工廠實現,實現程式碼模組之間的解耦
缺點:
每次為工廠模式新增新的產品時都要編寫一個新的產品類,同時還要引入抽象層,回導致類結構的複雜