簡單工廠模式
1. 定義:
- 屬于建立型模式,又叫做靜态工廠方法,但不屬于23種GOF設計模式之一。
- 由一個工廠對象決定建立出哪一種産品類的執行個體。簡單工廠模式是工廠模式家族中最簡單實用的模式,可以了解為是不同工廠模式的一個特殊實作。
- 将“類執行個體化的操作”與“使用對象的操作”分開,讓使用者不用知道具體參數就可以執行個體化出所需要的“産品”類,進而避免了在用戶端代碼中顯式指定,實作了解耦。
2. 适用場景:
- 工廠類負責建立的對象比較少;
- 客戶隻知道傳入工廠類的參數,對于如何建立對象(邏輯)不關心;
- 由于簡單工廠很容易違反高内聚責任配置設定原則,是以一般隻在很簡單的情況下應用;
3. 優缺點:
- 優點:通過使用工廠類,調用者僅僅需要負責“消費”對象就可以了。而不必管這些對象究竟如何建立及如何組織的,明确了各自的職責和權利,有利于整個軟體體系結構的優化。
- 缺點:由于工廠類集中了所有執行個體的建立邏輯,違反了高内聚責任配置設定原則;它所能建立的類隻能是事先考慮到的,如果需要添加新的類,則就需要改變工廠類了。當系統中的具體産品類不斷增多時候,可能會出現要求工廠類根據不同條件建立不同執行個體的需求.這種對條件的判斷和對具體産品類型的判斷交錯在一起,很難避免子產品功能的蔓延,對系統的維護和擴充非常不利;
- 這些缺點在 工廠方法模式 中得到了一定的克服。
4. Android源碼中的展現
如建立Bitmap對象的時候,例如通過資源id擷取Bitmap對象:
Bitmap bitmap=BitmapFactory.decodeResource(
getResources(), R.drawable.ic_launcher);
5. 執行個體示範:
以寵物店買貓為例
- 首先建立一個抽象類cat
abstract class Cat {
public abstract void show();
}
- 然後建立兩個子類,波斯貓和虎斑貓
class CatA extends Cat {
@Override
public void show() {
LjyLogUtil.i("A-波斯貓:喵喵喵~");
}
}
class CatB extends Cat {
@Override
public void show() {
LjyLogUtil.i("B-虎斑貓:喵喵喵~~~");
}
}
- 建立工廠類CatFactory,提供了兩種貓咪可選,客戶隻需要知道想買什麼品種的貓,而不需要關心他是如何産生的,這是簡單工廠模式的核心
class CatFactory {
public enum CatType {
TYPE_A,
TYPE_B
}
public static Cat newCat(CatType catType) {
switch (catType) {
case TYPE_A:
return new CatA();
case TYPE_B:
return new CatB();
default:
return null;
}
}
}
- 最後就是在使用工廠類建立cat執行個體了
private void methodSimpleFactoryPattern() {
CatFactory.newCat(CatFactory.CatType.TYPE_A).show();
CatFactory.newCat(CatFactory.CatType.TYPE_B).show();
// try {
// CatFactory.newCat(2).show();
// } catch (NullPointerException e) {
// LjyLogUtil.i("沒有這一類Cat");
// }
}
工廠方法模式
1. 定義:
又稱工廠模式、多态工廠模式和虛拟構造器模式;
此模式的核心精神是封裝類中不變的部分,提取其中個性化善變的部分為獨立類,通過依賴注入以達到解耦、複用和友善後期維護拓展的目的。它的核心結構有四個角色,分别是抽象工廠,具體工廠,抽象産品,具體産品;
簡單工廠的弊端: 1.工廠類集中了所有執行個體(産品)的建立邏輯,一旦這個工廠不能正常工作,整個系統都會受到影響; 2.違背“開放 - 關閉原則”,一旦添加新産品就不得不修改工廠類的邏輯,這樣就會造成工廠邏輯過于複雜; 3.簡單工廠模式由于使用了靜态工廠方法,靜态方法不能被繼承和重寫,會造成工廠角色無法形成基于繼承的等級結構; 工廠方法模式如何解決上述問題:
工廠方法模式把具體産品的建立推遲到工廠類的子類(具體工廠)中,此時工廠類不再負責所有産品的建立,而隻是給出具體工廠必須實作的接口;
2. 适用場景
對于某個産品,調用者清楚地知道應該使用哪個具體工廠服務,執行個體化該具體工廠,生産出具體的産品來。Java Collection中的iterator() 方法即屬于這種情況。
隻是需要一種産品,而不想知道也不需要知道究竟是哪個工廠為生産的,即最終選用哪個具體工廠的決定權在生産者一方,它們根據目前系統的情況來執行個體化一個具體的工廠傳回給使用者,而這個決策過程對于使用者來說是透明的。
3. Android源碼中的展現
如常用的Retrofit中的Converter.Factory ,CallAdapter.Factory即為抽象工廠類,它們的子類即為具體工廠類:
private RetrofitUtil() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BaseUrl.getBaseUrl())
//配置okhttp
.client(getOkHttpClient())
//支援gson
.addConverterFactory(GsonConverterFactory.create())
//增加傳回值為Oservable<T>的支援,RxJava
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
apiService = retrofit.create(ApiService.class);
}
3. 執行個體示範
以寵物店買鴨子為例
- 建立抽象鴨子類
abstract class Duck {
public abstract void show();
}
- 建立兩個鴨子子類
class DuckA extends Duck {
@Override
public void show() {
LjyLogUtil.i("DuckA:呀呀呀~");
}
}
class DuckB extends Duck {
@Override
public void show() {
LjyLogUtil.i("DuckB:呀呀呀~");
}
}
前面這兩步和簡單工廠模式是一樣的,工廠方法模式相對于簡單工廠模式的最大優點就在于工廠類的可擴充性
- 建立抽象工廠類
abstract class DuckFactory {
public abstract Duck newDuck();
}
- 建立兩個具體工廠類
class DuckAFactory extends DuckFactory {
@Override
public Duck newDuck() {
return new DuckA();
}
}
class DuckBFactory extends DuckFactory {
@Override
public Duck newDuck() {
return new DuckB();
}
}
- 具體使用
private void methodFactoryMethod() {
DuckAFactory duckAFactory = new DuckAFactory();
duckAFactory.newDuck().show();
DuckBFactory duckBFactory = new DuckBFactory();
duckBFactory.newDuck().show();
}
- 也可以像下面這樣用反射建立工廠類(需要知道要建立的具體實作類,耦合度高)
class DuckFactort {
public <T extends Duck> T get(Class<T> duckClass) {
try {
Duck duck = (Duck) Class.forName(duckClass.getName()).newInstance();
return (T) duck;
} catch (Exception e) {
return null;
}
}
}