工廠方法模式 Factory Method Pattern
864 字
4 分鐘
工廠方法模式 Factory Method Pattern
目的
定義可生成物件的介面,但讓子類別決定該實體化哪種類別的物件。讓類別把實體化的程序推遲給子類別去實作。
適用
- 當類別無法明指想要生成的物件類別時。當類別希望子類別去指定想要生成的物件類型時。將類別將權力下放一個或多個子類別,你又希望將「交付給哪些子類別」的知識集中在一個地方時。
結構及成員
Collaborations: Creator的子類別必須定義Factory Method實體,以回傳適當的Concrete Product物件。

- Product: like the Document定義Factory Method所造物件的介面。ConcreteProduct: like the MyDocument.具體實作出Product介面。AbstractProduct: like the ScrollBar, AbstractProductA宣告某成品物件類型之介面。Creator: like the Application宣告Factory Method,它會回傳Product類型的物件(ConcreteProduct)。ConcreteCreator: like the MyApplicationOverride Factory Method以傳回ConcreteProduct的物件個體。
影響結果
好處
- 替子類別預留掛鉤(Provides hooks for subclasses),以Factory Method的類別產生物件比直接產生物件更有彈性,只要Override他的方法,就能生成特殊的物件。連接平行地位的類別階層(Connects parallel class hierarchies)。一般來說,Factory Method只會被Creator引用,但不一定非得如此,也可以用在平行地位類別階層的關係。如下圖所示,Figure和Manipulator會平行地各自發展。每個Figure類別預留相對應的Factory Method CreateManipulator(),讓Client能建立與Figure相對應的Manipulator。Figure也可以將自己的CreateManipulator()寫成回傳一個預設的Manipulator物件實體。可以理解為:ConcreteCreator 跟 ConcreteProduct 會成對的增加。

平行地位類別階層通常會發生在「類別將某些權責委託給其他類別處理」的情況,如繪圖程式中,特定操弄圖形的動作,**如:伸長直線要移動某個端點;伸長圖形可以移動好幾個點;伸長文字方塊要調整行距……**因此,需要被Create的Manipulator [註:Manipulator地位同Product] 也會不一樣(以操作為例,在繪圖程式中,不同的繪圖物件要有不同的Manipulator物件處理不同的行為)。
但儘管如此,一個Factory(Figure)仍只能製造一種Product(Minupulator),因此如果要讓一個Factory可以製造多個Product,或多個同Style的Product,詳見 Abstract Factory Pattern。
壞處
- 潛在的缺點,客戶碼必須自Creator類別衍生出子類別,才能造出特定的ConcreteProduct物件。
實作
兩種主要形式
- Creator是Abstract Class,Factory Method只是空殼。Creator是Concrete Class,Factory Method有預設行為。
參數化Factory Method
可傳入參數指明要產生什麼Product。
命名慣例
好的命名慣例會讓Factory Method更一目瞭然。
Example: DBConnection Factory
//Interface: DBConnection
package db.connection;
public interface DBConnection { void getConnection();
}//Class: MySQLDBConnection
package db.connection;
public class MySQLDBConnection implements DBConnection { public void getConnection(){ System.out.println("MySQL DB is connected"); }
}//Class: JavaDBConnection
package db.connection;
public class JavaDBConnection implements DBConnection{ public void getConnection(){ System.out.println("Java DB is connected"); }
}//Class: OracleDBConnection
package db.connection;
public class OracleDBConnection implements DBConnection{ public void getConnection(){ System.out.println("Oracle DB is connected"); }
}//Interface: DBConnectionFactory
package db.connection;
public interface DBConnectionFactory { DBConnection createConnection();
}//Interface: MyDBConnectionFactory
package db.connection;
public class MyDBConnectionFactory implements DBConnectionFactory{ private String type; public MyDBConnectionFactory(String type){ this.type=type; }
public DBConnection createConnection(){ if (type.equalsIgnoreCase("Oracle")){ return new OracleDBConnection(); } else if (type.equalsIgnoreCase("MySQL")){ return new MySQLDBConnection(); } else if (type.equalsIgnoreCase("JavaDB")){ return new JavaDBConnection(); } else { //default product return new OracleDBConnection();
} } }}//Class: Main
package db.connection;
public class Main {
public static void main(String[] args) { MyDBConnectionFactory factory = new MyDBConnectionFactory("JavaDB"); factory.createConnection().getConnection();
factory = new MyDBConnectionFactory("MySQL"); factory.createConnection().getConnection();
factory = new MyDBConnectionFactory("Oracle"); factory.createConnection().getConnection();
}
}Result:
Java DB is connectedMySQL DB is connectedOracle DB is connected文章分享
如果這篇文章對你有幫助,歡迎分享給更多人!
工廠方法模式 Factory Method Pattern
https://linziyou.info/posts/2020-09-30-工廠模式-factory-pattern/ 最後更新於 2020-09-30,距今已過 1979 天
部分內容可能已過時