spring中用到很多的設計模式,其中最典型的就是工廠模式。工廠模式又有以下三種:簡單工廠、工廠方法、抽象工廠。下面將對這三種模式一一進行講解。
1、簡單工廠:
當A對象需要調用B對象的方法時,我們一般會在A中new一個B實例(這種方式叫做硬編碼耦合),這樣做的缺點是一旦需求發生變化,需要使用C類來代替B時就要改寫A類的方法。假如應用中有1000個類以硬編碼的方式耦合了B,那搞起來可就費勁了。
這時“簡單工廠”模式就派上用場了。可以讓B類實現一個IB接口,並創建一個工廠類IBFactory,用於創建IB實例,而A類通過調用IBFactory來得到IB實例。
以下是代碼示例:
package com.lincoln.springDesignPattern; /** * Computer需要調用Output接口 */ public class Computer { private Output out; private String name; public Computer(Output out,String name){ this.out = out ; this.name = name ; } public void setName(String name) { this.name = name; } public void setOut(Output out) { this.out = out; } public void keyIn(String msg) { out.getData(msg); } public void print() { out.out(); } public static void main(String args[]){ Computer cp = new Computer(PrintFactory.getPrint(),"lincoln's computer ") ; cp.keyIn("spring in action..."); cp.keyIn("think in java..."); cp.print(); } }
下面是一個輸出接口:
package com.lincoln.springDesignPattern; /** * 一個輸出接口 */ public interface Output { int MAX_CACHE_LINE = 50; void out(); void getData(String msg); }
定義了兩個實現類:
package com.lincoln.springDesignPattern; /** * 第一個打印器 */ public class Printer implements Output { private String[] printData = new String[MAX_CACHE_LINE]; private int dataNum = 0; public void out() { while(dataNum > 0) { System.out.println("打印" + printData[0]); System.arraycopy(printData , 1, printData, 0, --dataNum); } } public void getData(String msg) { if (dataNum >= MAX_CACHE_LINE) { System.out.println("輸出隊列已滿!"); } else { printData[dataNum++] = msg; } } }
另一個實現類:
package com.lincoln.springDesignPattern; /** * 實現了Output接口 */ public class BetterPrinter implements Output { private String[] printData = new String[MAX_CACHE_LINE * 2]; private int dataNum = 0; public void out() { while(dataNum >=0 ) { System.out.println("printer2," + printData[0]); //System.arraycopy(printData , 1, printData, 0, --dataNum); } } public void getData(String msg) { if (dataNum >= MAX_CACHE_LINE * 2) { System.out.println("getData"); } else { printData[dataNum++] = msg; } } }
定義一個工廠,由這個工廠來覺得究竟使用哪個printer。
package com.lincoln.springDesignPattern; /** * 工廠類,生成Output實例 * @author slpei * */ public class PrintFactory { public static Output getPrint() { return new Printer(); } }
使用簡單工廠的優勢是:把對象的使用者和創建者之間解耦,從而提高了系統的擴展性。缺陷是:當產品修改時,工廠類也要做相應修改。
2、工廠方法:
在簡單工廠中,由工廠類進行所有的邏輯判斷、實例創建。如果不想在工廠類中進行判斷,可以為不同的產品提供不同的工廠,不同的工廠生產不同的產品。
將上面的例子更改如下:
/** *定義一個輸出接口 */ public interface OutputFactory{ Output getOutput(); }
然后定義兩個實現該接口的工廠:
package com.lincoln.springDesignPattern; /** * 工廠類,生成Output實例 * @author slpei * */ public class PrintFactory implements OutputFactory{ public static Output getPrint() { return new Printer(); } }
package com.lincoln.springDesignPattern; /** * 工廠類,生成Output實例 * @author slpei * */ public class BetterPrintFactory implements OutputFactory{ public static Output getPrint() { return new BetterPrinter(); } }
這樣,在Computer中需要用到哪個printer只需調用該printer對應的工廠。
很顯然,上面的例子帶來了另一個耦合:產品和工廠之間的耦合。
為解決掉上述問題,可以再新增一個工廠類,該工廠類用於生成不同的工廠,這個類就叫做抽象工廠類:
package com.lincoln.springDesignPattern; /** * 抽象工廠類,生成工廠實例 * @author slpei * */ public class OutputFactoryFactory{ public static Output getPrint( String type ) { if("betterPrinter".equals(type)){ return new BetterPrinter(); }else{ return new Printer(); } } }
現在只需在Computer中創建獲取OutputFactoryFactory從而創建自己所需的產品。
spring容器就是個大型的抽象工廠,不僅可以創建普通的bean實例,也可以創建bean工廠。