spring设计模式——简单工厂、工厂方法、抽象工厂

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

posted @ 2013-07-16 11:21  lincolnPei  阅读(9098)  评论(0编辑  收藏  举报