標籤:設計模式 原廠模式 Factory 方法 android
簡單工廠&Factory 方法
一直以來總是分不清簡單工廠,Factory 方法,抽象工廠這三個設計模式的區別,倒不是不理解其區別,而是總是記憶混淆,傻傻分不清楚,所以再重新總結一下區別,並記錄下來,下次再混淆時,可以拿出來看看。這節先說簡單工廠和Factory 方法,下一節再說抽象工廠。
Factory 方法中其實就包含了簡單工廠,簡單工廠也稱為靜態Factory 方法,
簡單原廠模式(Simple Factory)類圖
簡單原廠模式又稱為靜態Factory 方法模式,是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 方法模式
Factory 方法模式(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產品了。
設計模式的應用還是要根據其使用情境來決定,簡單工廠升級為Factory 方法,是因為需要封裝工廠類,提供給客戶類最大的自由和擴充性,但又對工廠的內部邏輯進行封裝。
但不是說簡單工廠就沒有Factory 方法好用,當客戶類User本身也是內部封裝的一部分,我們可以很方便的去修改工廠類,或者產品的增加可能很小,比如Phone,本來就只有GSMPhone,CDMAPhone,過了很久,突然出現了CDMALTEPhone,那也只需要在工廠類中增加這個類的生產即可。也許再出現一個新的XXXPhone也要幾年之後了。
Android中的Factory 方法簡單工廠
Android源碼中有很多的Factory 方法的使用,其中大多是靜態Factory 方法,也即是最開始說的簡單工廠,前面也說過了,使用什麼工廠是根據需求來看的,靜態Factory 方法是Factory 方法的一個特例,雖然不似Factory 方法那麼靈活,但是對於很多不需要建立多個工廠來建造產品的情況下,靜態Factory 方法反而簡單快捷。
例如BitmapFactory,通過public static Bitmap decodeFile(String pathName)靜態方法,從檔案中讀取並建立Bitmap對象。
還比如Telephony中的PhoneFactory,通過public static void makeDefaultPhones(Context context) 靜態方法建立,並通過PhoneFactory.getDefaultPhone()擷取建立好的
還有NetworkStatsFactory,WebViewFactory這些都是簡單工廠的應用。
除了Framework,很多系統應用也用到了Factory 方法,就不一一列舉了。
Factory 方法
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則是具體產品。
Android中的設計模式-Factory 方法模式