天天看點

普通工廠模式、工廠方法模式、抽象工廠模式

  • 概述
屬于建立型設計模式,需要生成的對象叫做産品 ,生成對象的地方叫做工廠 。

1.普通工廠模式

使用場景:

在任何需要生成複雜對象的地方,都可以使用工廠方法模式。

準備:

定義一個接口:

public interface  Api {
    public void say();
}
           

編寫幾個實作接口的方法:

public class Impl1 implements Api {
    @Override
    public void say() {
        System.out.println("impl-1 實作");
    }

}
           
public class Impl2 implements Api {
    @Override
    public void say() {
        System.out.println("impl-2實作");
    }
}
           
public class Impl3 implements Api {
    @Override
    public void say() {
        System.out.println("impl-3實作");
    }
}
           

1.1簡單(靜态)工廠:

public class SimpleFactory {
    public static final int imp1 = ;
    public static final int imp2 = ;
    public static final int imp3 = ;
    //對象生成方法
    public static Api createApi(int imp){
        switch (imp) {
            case imp1:
                return  new Impl1();
            case imp2:
                return  new Impl2();
            case imp3:
            default:
                return  new Impl3();
        }

    }
    //client方法
    public static void main(String[] args) {
        Api a = SimpleFactory.createApi(SimpleFactory.imp1);
        a.say();
    }
}
           

特點:

1 它是一個具體的類,非接口 抽象類。有一個重要的create()方法,利用if或者 switch建立産品并傳回。

2 create()方法通常是靜态的,是以也稱之為靜态工廠。

缺點:

1 擴充性差(我想增加一種面條,除了新增一個面條産品類,還需要修改工廠類方法)

2 不同的産品需要不同額外參數的時候 不支援。

1.2反射實作工廠模式:

public class ReflectFactory {
    //對象生成方法
    public static <T extends Api> T createApi(Class<T> t) {
        T re = null;
        try {
            re = (T)Class.forName(t.getName()).newInstance();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return re;
    }
    //client方法
    public static void main(String[] args) {
        Api a = ReflectFactory.createApi(Impl1.class);
        a.say();
    }
}
           

特點

1 它也是一個具體的類,非接口 抽象類。但它的create()方法,是利用反射機制生成對象傳回,好處是增加一種産品時,不需要修改create()的代碼。

缺點

這種寫法粗看牛逼,細想之下,不談reflection的效率還有以下問題:

1 個人覺得不好,因為Class.forName(clz.getName()).newInstance()調用的是無參構造函數生成對象,它和new Object()是一樣的性質,而工廠方法應該用于複雜對象的初始化 ,當需要調用有參的構造函數時便無能為力了,這樣像為了工廠而工廠,與直接new建立沒有太大差别。

2 不同的産品需要不同額外參數的時候 不支援。

1.3多方法工廠

public class MulFactory {
    public static Api createImpl1(){
        return new Impl1();
    }
    public static Api createImpl2(){
        return new Impl2();
    }
    public static Api createImpl3(){
        return new Impl3();
    }
    public static void main(String[] args) {
        Api a = MulFactory.createImpl1();
        a.say();
    }
}
           

特點:

解決不同的産品需要不同額外參數的時候 不支援的問題。

而多方法的工廠模式為不同産品,提供不同的生産方法,使用時 需要哪種産品就調用該種産品的方法,使用友善、容錯率高。

線上程池的工廠類Executors就是使用這個模式。

public class Executors {
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }
    ......
}
           

這個例子可以感受到工廠方法的魅力了吧:友善建立 同種類型的 複雜參數 對象。

2.工廠方法模式

工廠方法模式是簡單工廠模式的衍生,解決了許多簡單工廠模式的問題。首先完全實作‘開-閉 原則’,實作了可擴充。其次更複雜的層次結構,可以應用于産品結果複雜的場合。

工廠也由原先的方法程式設計接口如下:

public abstract class Factory {
    public abstract Api createApi();
}
           

有接口就有接口的實作:

public class Implfactory1 extends Factory{
    @Override
    public Api createApi() {
        return new Impl1();
    }

    public static void main(String[] args) {
        Factory fac = new Implfactory1();
        Api a =fac.createApi();
        a.say();
    }
}
           

是以沒個對象都需要一個獨立的工廠去進行聲明,但是擁有相同的工廠接口。

優點:

建立對象的接口,讓子類去決定具體執行個體化的對象,把簡單的内部邏輯判斷移到了用戶端代碼。工廠方法克服了簡單工廠違背開放-封閉原則的缺點,又保持了封裝對象建立過程的優點。

3抽象工廠模式

提供一個建立一系列相關或互相依賴對象的接口,而無需指定它們具體的類。

因為是一系列,是以我們需要更多的産品建立另一個産品的接口以及産品的一些實作:

public interface Apis {
    public void says();
}
           

産品的實作:

public class Impls1 implements Apis {
    @Override
    public void says() {
        System.out.println("Impls-1 實作");
    }

}
           

接下來進行一些列産品的工廠類建立,首先進行工廠接口的編寫:

public abstract class AbstractFactory {
    public abstract Api createApi();
    public abstract Apis createApis();
}
           

工廠類的實作(可以多實作,不同實作不同系列産品):

public class ExtendFactory extends AbstractFactory{
    @Override
    public Api createApi() {
        return new Impl1();
    }

    @Override
    public Apis createApis() {
        return new Impls1();
    }

    public static void main(String[] args) {
        AbstractFactory ab = new ExtendFactory();
        ab.createApi().say();
        ab.createApis().says();
    }
}
           

4總結

一句話總結工廠模式:友善建立 同種産品類型的 複雜參數 對象

工廠模式重點就是适用于 建構同産品類型(同一個接口 基類)的不同對象時,這些對象new很複雜,需要很多的參數,而這些參數中大部分都是固定的,so,懶惰的程式員便用工廠模式封裝之。

為了适應程式的擴充性,擁抱變化,便衍生出了 工廠方法模式、抽象工廠等模式。

繼續閱讀