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工厂。