工廠模式(Factory Pattern)和java反射機制優化思考

<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設計的基石,上層建築還是很複雜的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章