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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM