工廠方法模式
比如富士康是一個工廠,為其他外部廠商提供相同或者不同的產(chǎn)品,而外部廠商不用關(guān)心富士康內(nèi)部的實現(xiàn)過程,只需要接受結(jié)果即可。如果有新的產(chǎn)品,也只需要告訴富士康,富士康負責(zé)生產(chǎn)輸出就好。
因此工廠模式可大幅度降低模塊之間的耦合,加強擴展性。
應(yīng)用場景
需要生成一個或者多個復(fù)雜對象的具體實現(xiàn)
工廠模式分類
- 工廠方法模式
- 標(biāo)準(zhǔn)工廠
- 簡單工廠
- 反射工廠
- 緩存工廠
- 私有工廠
- 抽象工廠模式
本文主要介紹工廠方法模式。
工廠方法模式特點
- 一個抽象類可以實現(xiàn)多個具體類
具體實現(xiàn)
Q:使用工廠模式來判斷一個程序猿他是具體的什么樣的程序猿(PHP,Android,iOS,Java等等)
(一)標(biāo)準(zhǔn)工廠方法
1.建立一個接口來獲取程序猿類型
public interface CodeMonkey {
public void showCodeMonkeyType();//展示是什么類型的程序猿
}
2.實現(xiàn)接口生成不同類型的程序猿
Android程序猿:
public class AndroidCodeMonkey implements CodeMonkey {
@Override
public void showCodeMonkeyType() {
System.out.println("我是Android攻城獅");
}
}
iOS程序猿:
public class IosCodeMonkey implements CodeMonkey {
@Override
public void showCodeMonkeyType() {
System.out.print("我是iOS攻城獅");
}
}
3.建立抽象的工廠接口
public abstract class Factory {
public abstract CodeMonkey showCodeMonkeyType() ;
}
4.通過抽象的工廠接口進行具體類的實現(xiàn)
public class AndroidMonkeyFactory extends Factory {
@Override
public CodeMonkey showCodeMonkeyType() {
return new AndroidCodeMonkey();
}
}
public class IosMonkeyFactory extends Factory {
@Override
public CodeMonkey showCodeMonkeyType() {
return new IosCodeMonkey();
}
}
5.具體調(diào)用
CodeMonkey codeMonkey = new AndroidCodeMonkey();
codeMonkey.showCodeMonkeyType();
new IosCodeMonkey().showCodeMonkeyType();
6.輸出結(jié)果
我是Android攻城獅
我是iOS攻城獅
程序猿(產(chǎn)品)在創(chuàng)建過程中都是通過接口來進行生成,生成某一類型程序猿時降低了使用者和產(chǎn)品本身耦合
(二)簡單工廠模式(靜態(tài)工廠模式)
靜態(tài)工廠的方法是靜態(tài)的,不允許外部進行擴展更改,如果有內(nèi)容的更改需要對當(dāng)前靜態(tài)工廠進行更改。
代碼示例:
public class CodeMonkeyEasyFactory {
public final static String GENERATE_IOS = "android";
public final static String GENERATE_ANDROID = "ios";
public static CodeMonkey generateCodeMonkey(String flag) throws Exception {
CodeMonkey codeMonkey = null;
switch (flag){
case GENERATE_ANDROID:
codeMonkey = new AndroidCodeMonkey();
break;
case GENERATE_IOS:
codeMonkey = new IosCodeMonkey();
break;
default:
throw new Exception("UNDEFINED FLAG");
}
return codeMonkey;
}
}
上述靜態(tài)工廠在內(nèi)部已經(jīng)定義了iOS和Android的靜態(tài)常亮,使用過程中只需要外部傳入具體的數(shù)值,內(nèi)部進行判斷即可,但是若有新的程序猿產(chǎn)生,除了實現(xiàn)具體的程序猿,還需要對靜態(tài)工廠擴展增加。
外部調(diào)用:
CodeMonkeyEasyFactory.generateCodeMonkey(CodeMonkeyEasyFactory.GENERATE_ANDROID).showCodeMonkeyType();
CodeMonkeyEasyFactory.generateCodeMonkey(CodeMonkeyEasyFactory.GENERATE_IOS).showCodeMonkeyType();
顯示結(jié)果:
我是Android攻城獅
我是iOS攻城獅
(三)反射工廠
只需要實現(xiàn)具體的產(chǎn)品類型而不需要修改工廠,通過反射拋到上層直接讓外部使用獲取。
代碼示例:
1.泛型類型約束將具體類型拋到上層工廠進行處理
public abstract class IGenerator {
public abstract <T extends CodeMonkey>T generateCodeMonkey(Class<T> clazz) throws Exception;
}
2.實現(xiàn)具體產(chǎn)品內(nèi)容
public class CodeMonkeyReflexFactory extends IGenerator {
@Override
public <T extends CodeMonkey> T generateCodeMonkey(Class<T> clazz) throws Exception {
CodeMonkey codeMonkey = null;
codeMonkey = (CodeMonkey) Class.forName(clazz.getName()).newInstance();
return (T)codeMonkey;
}
}
調(diào)用方式:
new CodeMonkeyReflexFactory().generateCodeMonkey(AndroidCodeMonkey.class).showCodeMonkeyType();
顯示結(jié)果:
我是Android攻城獅
(四)緩存工廠
將復(fù)雜對象或者頻繁使用的內(nèi)容作為一個長期的存儲,再次使用時直接進行提取
代碼示例:
public class CodeMonkeyCacheFactory extends IGenerator {
private Map<String, CodeMonkey> map = new HashMap<>();
@Override
public <T extends CodeMonkey> T generateCodeMonkey(Class<T> clazz) throws Exception {
CodeMonkey CodeMonkey = null;
if (map.containsKey(clazz.getName()))
CodeMonkey = map.get(clazz.getName());
else {
CodeMonkey = (CodeMonkey) Class.forName(clazz.getName()).newInstance();
map.put(clazz.getName(), CodeMonkey);
}
return (T) CodeMonkey;
}
}
將具體的產(chǎn)品類型存儲于hasmap,再次使用時可直接提取使用。
調(diào)用方式:
new CodeMonkeyCacheFactory().generateCodeMonkey(AndroidCodeMonkey.class).showCodeMonkeyType();
顯示結(jié)果:
我是Android攻城獅
(五) 私有產(chǎn)品構(gòu)造
限制外部使用new XXX()的方式進行創(chuàng)建
public class CodeMonkeyPrivateFactory extends IGenerator {
public <T extends CodeMonkey> T generateCodeMonkey(Class<T> clazz) throws Exception {
CodeMonkey iPhone = null;
Class phone = Class.forName(clazz.getName());
//拿到構(gòu)造器不檢測權(quán)限
phone.getDeclaredConstructor().setAccessible(true);
iPhone = (CodeMonkey) phone.newInstance();
return (T) iPhone;
}
}
調(diào)用方式:
new CodeMonkeyPrivateFactory().generateCodeMonkey(AndroidCodeMonkey.class).showCodeMonkeyType();
顯示結(jié)果:
我是Android攻城獅
總結(jié)
以上就是工程模式的介紹.降低模塊耦合,提高擴展性,有新的產(chǎn)品內(nèi)容出現(xiàn)只需要擴展工廠即可完成。