1.前言
還記得建造者模式嗎?通過一步步的設置,或者實現不同的Builder類可以創建出不同的對象。但是,擴展性仍覺得不夠,要么設置屬性的操作空間很小,要么必須得按流程辦事。所以希望有一種設計模式能夠更加自由地創建對象,對外是統一的調用方法,對內則提供的對象可以獨立地構造。
2.概念
工廠方法模式要求定義一個用于創建對象的接口,讓子類決定實例化哪個類。還記得依賴倒置原則嗎?不記得可以看這里。依賴倒置可以將代碼的具體實現封裝起來,對調用者隱藏內部操作,降低了彼此之間的耦合度,使業務邏輯產生的變化只會影響實現類。而工廠方法模式完全符合這項原則。
3.場景
工廠要生產兩種油性筆,根據使用的材料分為高端金屬外殼和大眾塑料外殼。要注意的是,筆具有寫的功能,而工廠具有生產的功能。
4.寫法
第一步,聲明產品和工廠的操作規范,方便客戶使用。
public interface Pen {
void write();
}
public interface Factory {
Pen produce();
}
第二步,分別實現兩種產品及生產產品的工廠。
public class MetalPen implements Pen {
@Override
public void write() {
System.out.println("我是高端金屬筆");
}
}
public class PlasticPen implements Pen {
@Override
public void write() {
System.out.println("我是大眾塑料筆");
}
}
public class MetalFactory implements Factory {
@Override
public Pen produce() {
return new MetalPen();
}
}
public class PlasticFactory implements Factory {
@Override
public Pen produce() {
return new PlasticPen();
}
}
第三步,客戶通知工廠開始生產。
public class Client {
public static void main(String[] args) {
new MetalFactory().produce().write();;
new PlasticFactory().produce().write();
}
}
以上就是最常用的工廠方法模式,稱為多工廠方法模式。當需要增加一種產品時,只需要實現對應的產品類和工廠類即可,非常方便。若因需修改產品時,僅修改對應的產品類即可。
細心的你發現了沒有,若產品數量一直增加下去,那豈不是要造一堆工廠,不符合實際呀。最好的辦法是,同一個工廠根據不同的設計圖生產不同的筆。所以引入另一種工廠方法模式,叫簡單工廠模式或者靜態工廠模式。開始對上面的代碼進行改造:
// 通過傳入的Class類和反射決定生產的產品
public class Factory {
public static <T extends Pen> T produce(Class<T> clz) {
Pen pen = null;
try {
pen = (Pen) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) pen;
}
}
public class Client {
public static void main(String[] args) {
// 讓我生產啥就生產
Factory.produce(MetalPen.class).write();
Factory.produce(PlasticPen.class).write();
}
}
現在的代碼,比原來的少了一層工廠抽象,更加簡潔,而且動態性增強。傳入的產品類相當于圖紙,更符合現實生活中的情況。
5.總結
工廠方法模式是一個很好的設計模式,結構清晰,有效地封裝變化。但是會增加代碼層級,引入較多的類,所以用new就可以創建的對象無需使用工廠方法模式。這里提供的產品是完整的對象,細節在構造函數中封裝,那么若工廠是生產零部件,由用戶自己組裝時,又會如何呢?不同工廠生產不同的產品,同一個工廠生產不同檔次的產品,如何按需組合?下一篇抽象工廠模式,將會探討這個問題。