Android中的設計模式-工廠方法模式

簡單工廠&工廠方法

一直以來總是分不清簡單工廠,工廠方法,抽象工廠這三個設計模式的區別,倒不是不理解其區別,而是總是記憶混淆,傻傻分不清楚,所以再重新總結一下區別,並記錄下來,下次再混淆時,可以拿出來看看。這節先說簡單工廠和工廠方法,下一節再說抽象工廠。

工廠方法中其實就包含了簡單工廠,簡單工廠也稱爲靜態工廠方法,

簡單工廠模式(Simple Factory)

類圖

這裏寫圖片描述
簡單工廠模式又稱爲靜態工廠方法模式,是工廠方法模式的一種,簡單工廠模式的實質是由一個工廠類根據傳入的參數,動態決定應該創建哪一個產品類(這些產品類繼承自一個父類或接口)的實例。注意這裏工廠類傳入的參數,是工廠類新建產品的依據,可以是一個字符串,也可以是自己定義的Enum或者Int值。

以一個汽車工廠爲例,可以生產3種不同類型的汽車,SUV,Sedan,MPV,每個汽車都有drive方法。如果不使用簡單工廠而是直接創建的話,如下面的例子。

public class User {
    public static SUV suv;
    public static void main(String[] args) {
        suv=new SUV();
        suv.drive();
    }

}
class SUV{
    public void drive(){
        System.out.println("SUV is driving");
    }
}
class Sedan{
    public void drive(){
        System.out.println("Sedan is driving");
    }
}
class MPV{
    public void drive(){
        System.out.println("MPV is driving");
    }
}

乍看起來沒問題,想要什麼產品,那就直接新建一個就好了,不過問題在於,對於使用產品的類,只能持有對應產品的對象,例如上面的例子,我持有SUV的對象,然後新建SUV的對象,當有一天有了新的產品了,並且需要替換SUV。還需要修改使用的主體。這就使使用產品的主體和產品緊緊耦合在了一起。不利於代碼的複用和拓展。

把上面的代碼稍微修改一下,將所有車輛抽象爲一個Vehicle接口,讓User持有一個Vehicle對象,新建一個工廠類,根據傳入的參數不同,返回不同的對象給User使用。並且工廠類創建產品的函數是靜態的,這樣就不需要先創建一個工廠類了。

代碼:


interface Vehicle{
    public void drive();
}
class SUV implements Vehicle {
    @Override
    public void drive(){
        System.out.println("SUV is driving");
    }
}
class Sedan implements Vehicle{
    @Override
    public void drive() {
        System.out.println("Sedan is driving");
    }

}
class MPV implements Vehicle{
    @Override
    public void drive(){
        System.out.println("MPV is driving");
    }
}

enum VehcleType{
    suv,sedan,mpv
}
public class SimpleFactory {
    public static Vehicle makeVehicle(VehcleType type){
        switch(type){
        case suv:
            return new SUV();
        case sedan:
            return new Sedan();
        case mpv:
            return new MPV();
        default:
            break;
        }
        return null;

    }
}

測試代碼:


public class User {
    public static Vehicle mVehicle;
    public static void main(String[] args) {
        mVehicle=SimpleFactory.makeVehicle(VehcleType.suv);
        mVehicle.drive();
    }

}

這樣就好多了。不過有些情況還是不夠好,比如:
當我需要生產一種新的車型,比如敞篷車 Convertible. 但是我在SimpleFactory.makeVehicle時,並沒有這種車型,那就需要修改SimpleFactory類讓它增加一個case判斷,並新建一個Convertible對象。但是我們並不希望SimpleFactory這個工廠類開放給用戶,也就造成了沒辦法去增加車型。 如何才能讓User任意的增加車型呢? 這就擴展出了工廠方法模式

工廠方法模式(Factory Method)

繼續上面的說,User可以只知道一個Vehicle接口對象和一個Factory接口對象,對於SUV來說它實現了Vehicle接口,同時也需要SUVFactory來實現Factory接口並創建它,這樣對User來說,只需要創建一個SUVFactory對象,然後通過SUVFactory類創建一個SUV對象。 如果客戶自己想增加一個Convertible產品。那只需要實現自己的Convertible類和ConvertibleFactory類。然後用同樣的方式生產即可。

類圖

這裏寫圖片描述

代碼:

車輛相關

public interface Vehicle {
    public void drive();
}
class SUV implements Vehicle {
    @Override
    public void drive(){
        System.out.println("SUV is driving");
    }
}
class Sedan implements Vehicle{
    @Override
    public void drive() {
        System.out.println("Sedan is driving");
    }

}
class MPV implements Vehicle{
    @Override
    public void drive(){
        System.out.println("MPV is driving");
    }
}

工廠相關

public interface Factory {
    public Vehicle makeVehicle();

}

class SUVFactory implements Factory{
    @Override
    public Vehicle makeVehicle() {

        return new SUV();
    }

}
class SedanFactory implements Factory{
    @Override
    public Vehicle makeVehicle() {

        return new Sedan();
    }

}
class MPVFactory implements Factory{
    @Override
    public Vehicle makeVehicle() {

        return new MPV();
    }

}

客戶類:
public class User {
public static Vehicle mVehicle;
public static Factory mFactory;
public static void main(String[] args) {
mFactory=new SUVFactory();
mVehicle=mFactory.makeVehicle();
mVehicle.drive();
}

}

這時,我們想要改生產Convertible車輛,只需要增加Convertible和對應工廠,並修改客戶類的實現即可:

class Convertible implements Vehicle{
    @Override
    public void drive(){
        System.out.println("Convertible is driving");
    }
}
class ConvertibleFactory implements Factory{
    @Override
    public Vehicle makeVehicle() {

        return new Convertible();
    }

}
public class User {
    public static Vehicle mVehicle;
    public static Factory mFactory;
    public static void main(String[] args) {
        mFactory=new ConvertibleFactory();
        mVehicle=mFactory.makeVehicle();
        mVehicle.drive();
    }

}

這時,生產出來的就是Convertible產品了。
設計模式的應用還是要根據其使用場景來決定,簡單工廠升級爲工廠方法,是因爲需要封裝工廠類,提供給客戶類最大的自由和擴展性,但又對工廠的內部邏輯進行封裝。
但不是說簡單工廠就沒有工廠方法好用,當客戶類User本身也是內部封裝的一部分,我們可以很方便的去修改工廠類,或者產品的增加可能很小,比如Phone,本來就只有GSMPhone,CDMAPhone,過了很久,突然出現了CDMALTEPhone,那也只需要在工廠類中增加這個類的生產即可。也許再出現一個新的XXXPhone也要幾年之後了。

Android中的工廠方法

簡單工廠

Android源碼中有很多的工廠方法的使用,其中大多是靜態工廠方法,也即是最開始說的簡單工廠,前面也說過了,使用什麼工廠是根據需求來看的,靜態工廠方法是工廠方法的一個特例,雖然不似工廠方法那麼靈活,但是對於很多不需要創建多個工廠來建造產品的情況下,靜態工廠方法反而簡單快捷。

例如BitmapFactory,通過public static Bitmap decodeFile(String pathName)靜態方法,從文件中讀取並新建Bitmap對象。
還比如Telephony中的PhoneFactory,通過public static void makeDefaultPhones(Context context) 靜態方法創建,並通過PhoneFactory.getDefaultPhone()獲取創建好的
還有NetworkStatsFactory,WebViewFactory這些都是簡單工廠的應用。
除了Framework,很多系統應用也用到了工廠方法,就不一一列舉了。

工廠方法

Java庫中的ThreadFactory類作爲抽象工廠,定義如下:

public interface ThreadFactory {
    Thread newThread(Runnable r);
}

Android中常用的AsyncTask,在其中就新建了一個具體的工廠(還有MMS應用中的BackgroundLoaderThreadFactory的實現,類似):

    private static final ThreadFactory  sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

ThreadFactory的使用一般用在作爲新建ThreadPoolExecutor的參數,在ThreadPoolExecutor中調用getThreadFactory().newThread()來新建一個工作線程,這裏面Runnable可以理解爲抽象產品,而Thread則是具體產品。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章