創建型模式:工廠方法
個人博客原文
創建型模式:工廠方法
簡介
姓名:工廠方法
英文名:Factory method Pattern
價值觀:擴展是我的專屬
個人介紹:
Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses. (定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。)
(來自《設計模式之禪》)
你要的故事
還記得上一篇 單例模式 中的故事麽?小明開著汽車去旅遊、去學校、去聚會。這一次還是延續小明的故事,一個故事能講 2 個設計模式,不容易呀。。。(每次想故事都想破腦袋,每一篇文章至少有 3 個故事從腦子裏閃過,但最終留下的只有一個適合,為了就是能比較清晰簡單的說明設計模式中的關鍵要點。)
簡單工廠
小明家裏以前不算很富裕,但是還是有一個不錯的車庫,什麽汽車、摩托車、自行車啥的都放在這個車庫裏。小明每次要出去,都會到車庫裏面挑合適的車出發。比如,小明最近期末考試了,騎摩托車去學校考試,考完試之後,小明就準備去旅遊,這次決定自駕遊,開著自己家的小汽車去。這個場景我們用代碼描述下。
public class SimpleFactoryTest { public static void main(String[] args) { XiaoMing xiaoMing = new XiaoMing(); // 小明騎摩托車去學校 IVehicle motorcycle = GarageFactory.getVehicle("motorcycle"); xiaoMing.goToSchool(motorcycle); // 小明開汽車去旅遊 IVehicle car = GarageFactory.getVehicle("car"); xiaoMing.travel(car); } } /** * 車庫 */ class GarageFactory { public static IVehicle getVehicle(String type) { if ("car".equals(type)) { return new Car(); } else if ("motorcycle".equals(type)) { return new Motorcycle(); } throw new IllegalArgumentException("請輸入車類型"); } } /** * 交通工具 */ interface IVehicle { void run(); } /** * 汽車 */ class Car implements IVehicle { @Override public void run() { System.out.println("開汽車去。。。。"); } } /** * 摩托車 */ class Motorcycle implements IVehicle { @Override public void run() { System.out.println("騎摩托車去。。。。"); } } class XiaoMing { public void goToSchool(IVehicle vehicle) { System.out.println("小明去學校"); vehicle.run(); } public void travel(IVehicle vehicle) { System.out.println("小明去旅遊"); vehicle.run(); } }
上面代碼看懂了麽? 小明家裏有一個車庫 GarageFactory,裏面放著汽車 Car 和摩托車 Motorcycle,小明要出去的時候,就到車庫選擇車,通過傳遞參數給 GarageFactory.getVehicle(),指明要什麽車,然後小明就騎著車出發了。
這個代碼真正的術語叫:簡單工廠模式(Simple Factory Pattern),也叫做靜態工廠模式。它是工廠方法中的一個實現方式,從字面理解就可以知道,它是最簡單的工廠方法實現方式。它有一點點小缺陷,就是擴展性不夠好,在上面代碼中,小明只能騎摩托車或者開汽車,如果小明要騎單車出去呢?勢必得在 GarageFactory 中添加 if 是自行車的邏輯。這違反了哪條規則了?是不是那個允許擴展,拒絕修改的開閉原則
不是說簡單工廠這種實現方式不好,而是擴展性不夠,在平時的開發中,簡單工廠模式也用得不少。在這個小明家裏車不多的情況下,用一個車庫也是合適的。
工廠方法
小明老爸近幾年賺了不少,車迷的兩父子一直買車,家裏的車越來越多,這時候,他們決定多建幾個車庫,按車類型放置。比如,有一個汽車庫,一個摩托車庫。這時候小明要開汽車就去汽車庫,要騎摩托車就去摩托車庫。代碼實現如下。
public class FactoryMethodTest {
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing();
// 小明騎摩托車去學校
VehicleGarage motorcycleGarage = new MotorcycleGarage();
IVehicle motorcycle = motorcycleGarage.getVehicle();
xiaoMing.goToSchool(motorcycle);
// 小明開汽車去旅遊
VehicleGarage carGarage = new CarGarage();
IVehicle car = carGarage.getVehicle();
xiaoMing.travel(car);
}
}
interface VehicleGarage {
IVehicle getVehicle();
}
/**
* 汽車車庫
*/
class CarGarage implements VehicleGarage {
@Override
public IVehicle getVehicle() {
return new Car();
}
}
/**
* 摩托車車庫
*/
class MotorcycleGarage implements VehicleGarage {
@Override
public IVehicle getVehicle() {
return new Motorcycle();
}
}
上面代碼重用了簡單工廠實現方式的交通接口以及摩托車和汽車的實現類。代碼中有 2 個車庫,一個是汽車車庫 CarGarage,一個是摩托車庫 MotorcycleGarage。如果小明要騎自行車,只需要建一個自行車車庫,完全不用去修改汽車車庫或者摩托車車庫,就非常符合開閉原則,擴展性大大的提高。
總結
工廠方法模式可以說在你能想到的開源框架源碼中必定會使用的一個設計模式,因為開源框架很重要一點就是要有擴展性,而工廠方法模式恰恰具有可擴展性。弄懂了工廠方法模式,以後看開源代碼就很得心應手啦。
參考資料:《大話設計模式》、《Java設計模式》、《設計模式之禪》、《研磨設計模式》、《Head First 設計模式》
代碼鏈接:Factory method Pattern
希望文章對您有所幫助,設計模式系列會持續更新,感興趣的同學可以關註公眾號 LieBrother,第一時間獲取文章推送閱讀,也可以一起交流,交個朋友。
公眾號之設計模式系列文章
創建型模式:工廠方法