<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">GOF的工廠模式是最基礎的一種創建型設計模式,其適用於創建同一接口的不同實現子類,</span>
其優點是:將使使用者更加方便使用,而不關心具體的創建邏輯
缺點是:每增加一個接口的子類,必須修改工程類的相關邏輯(後面我們用java的反射機制進行優化)
從上面UML圖看到,我們設置了一個Shape接口,並且實現了三個子類,我們通過ShapeFactory來根據不同的名稱返回不同的子類實例,通過FactoryPatternDemo進行的測試。邏輯很簡單,不再詳述。
public class ShapeFactory {
//使用 getShape 方法獲取形狀類型的對象
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}
基於以上面ShapeFactory的實現,我們思考到,如果我們再增加一個子類實現,那麼ShapeFactory必須進行相應的修改源碼,並重新進行編譯,這不是我們想要的結果。如果能不改變ShapeFactory的內容,而是將需要調用的子類寫在配置文件中多好,這樣ShapeFactory從配置文件中接收到需要返回的子類名稱,返回相應的子類實例。說到這裏,大家也許有點耳熟,這和spring中的依賴注入不很相似嗎,能想到這裏說明你很厲害了。不錯,這個就需要java的反射機制來實現(spring依賴注入的內部原理就是依賴java的反射機制),java.lang.Class類閃亮登場。
利於java.lang.Class類,我們可以通過Class.forName方法用類的詳細名稱(含包名)得到一個這個類的Class,之後就可以通過這個Class類進行一系列的操作了,實例化一個這個類的類對象newInstance()(調用不含參數的構造函數實例化),查看他的構造方法Constructor,方法Method,成員變量Field,執行Method(可能需要java.lang.reflect中的類)。
回到上面,我們如何優化上面的工廠模式,思路是這樣的,首先將將要調用的子類名放到配置文件中(好處是在改變調用的時候並不需要改變其他的代碼),然後在Factory中用Class解析這個類,並實例化返回。最後在Demo中進行調用。思路很簡單
properties文件如下:
shape.className=factoryPattern.Rectangle
Factory代碼如下public class ShapeFactory {
public Shape getShape(String shapeClassName){
Shape targetShape=null;
Class oneClass=null;
try {
oneClass=Class.forName(shapeClassName);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("不能正確獲取類");
}
try {
targetShape=(Shape) oneClass.newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("不能正確創建實例");
}
return targetShape;
}
調用:
public static void main(String[] args) {
String targetClassName=ClassNameConfig.getProperty("shape.className");
System.out.println("targetClassName:"+targetClassName);
ShapeFactory shapeFactory=new ShapeFactory();
Shape targetShape=shapeFactory.getShape(targetClassName);
targetShape.draw();
}
這樣,當修改調用子類時,只需要修改配置文件即可。當然,對於簡單的工廠模式應用沒必要如此繁瑣理解了這個,也就不難理解Spring的Ioc技術,Spring的配置文件換成了xml文件,而且設計比較複雜,調用程序變成了所謂的spring容器,當然這只是spring設計的基石,上層建築還是很複雜的。