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