今天聊一聊你們最耳熟能詳的設計模式,『工廠模式』。實際上這個設計模式有三個變種,分別是『簡單工廠模式』、『工廠方法模式』以及『抽象工廠模式』,可能大部人所熟知的是前兩種,抽象工廠模式有必定的場景限制,不多出如今你們的視野中,不過今天咱們一併談一談。java
簡單工廠說白了就是一個超級工廠,他能夠生產各類各樣的產品,產品之間無關聯,好比:git
public interface SimpleFactory {
//生產一個冰箱
Refrigerator createRefiger();
//生產一個空調
AirConditioning createAirConditioning();
//生產一個 TV
TV createTV();
}
複製代碼
通常也會有一個默認的實現:程序員
public class DefaultSimpleFactory implements SimpleFactory{
@Override
public Refrigerator createRefiger() {
return new Refrigerator();
}
@Override
public AirConditioning createAirConditioning() {
return new AirConditioning();
}
@Override
public TV createTV() {
return new TV();
}
}
複製代碼
這就是一個簡單工廠模式,很是的簡單,尚未很強的抽象性。github
Spring 的 BeanFactory 其實就是一個簡單工廠模式,他定義了一個 BeanFactory 工廠,而後會有 DefaultListableBeanFactory 去實現這個工廠聲明的全部能力。面試
其實理論上來講,能夠把簡單工廠模式理解爲工廠方法模式的一種特例,將他的那個超級大工廠拆分紅多個工廠就是工廠方法模式了。設計模式
一樣有一個抽象接口表述一個工廠:微信
public interface MethodFactory {
//生產一個冰箱
Refrigerator createRefiger();
//生產一個空調
AirConditioning createAirConditioning();
//生產一個 TV
TV createTV();
}
複製代碼
簡單工廠是用一個 DefaultFactory 完成了工廠全部的能力要求。可是如今咱們的廠家變多了,有格力冰箱、海爾冰箱、海信冰箱等等,他們生產的冰箱或空調都不同,若是用簡單工廠的話,就須要作區分,增長更多的方法,生產格力冰箱的,生產海爾冰箱的,很是的醜陋。markdown
工廠方法模式,須要區分不一樣的工廠,這裏咱們建立格力工廠、海爾工廠和海信工廠。ide
public class GeliFactory implements MethodFactory {
@Override
public Refrigerator createRefiger() {
return new GeliRefrigerator();
}
@Override
public AirConditioning createAirConditioning() {
return new GeliAirConditioning();
}
@Override
public TV createTV() {
return new GeliTV();
}
}
複製代碼
格力工廠返回的是格力的空調、格力的冰箱以及格力的電視機,海爾和海信也都會返回他們本身品牌的產品,這裏就不貼他們的代碼了,相似。oop
這樣,咱們的工廠方法對外提供了生產產品的能力,具體產生何種類型的產品,將由具體的工廠決定。這就是工廠方法模式,相信大部分人應該都不陌生。
Logpack 中就有一個典型的工廠方法,工廠抽象類 ILoggerFactory:
public interface ILoggerFactory {
Logger getLogger(String var1);
}
複製代碼
他有兩個具體的工廠實現這個 getLogger 方法,
public class NOPLoggerFactory implements ILoggerFactory {
public NOPLoggerFactory() {
}
public Logger getLogger(String name) {
return NOPLogger.NOP_LOGGER;
}
}
複製代碼
public class SubstituteLoggerFactory
implements ILoggerFactory {
//省略
public synchronized Logger getLogger(String name) {
SubstituteLogger logger = (SubstituteLogger)this.loggers.get(name);
if (logger == null) {
logger = new SubstituteLogger(name, this.eventQueue, this.postInitialization);
this.loggers.put(name, logger);
}
return logger;
}//省略。。。。。
}
複製代碼
抽象工廠模式可能不如前二者常見,可是確是爲了補充前二者的,有特定的場景。
想象這麼一種狀況,你使用了工廠方法模式,你的工廠提供的能力很是多,能夠生產冰箱、電視、空調、洗衣機、電腦以及桌子等等,這樣你就會產生不少的工廠。
抽象工廠的做用就是在必定前提下,幫你分類這些工廠,好比按品牌分類,或者按照價格等級分類,這樣會大大縮減系統中的工廠數量。
這個前提就是你的這些工廠須要在兩個維度上具有共性:
專業術語就是『產品等級』和『產品族』兩個概念,說人話就是,這些工廠須要至少具備兩個共性,好比均可以按照類型區分紅三類,電視機、冰箱和空調,也能夠按照品牌區分紅海爾、海信和 TCL。
這樣他們就具有抽象工廠的前提條件,你能夠按照產品族合併工廠,正如我上面使用到的例子同樣,工廠對外提供生產電視、冰箱和空調三種能力,而系統按品牌存在三個工廠,因此從準確來講,我在工廠方法中使用的例子其實也是增強版的抽象工廠模式。
代碼例子就不舉例了,抽象工廠其實就是幫助減小系統的工廠數量的,但前提條件就是這些工廠要具有兩個及以上的共性。
但願你被面試官問道工廠方法和抽象工廠的區別的時候,能想起這一句話。
關注公衆不迷路,一個愛分享的程序員。
公衆號回覆「1024」加做者微信一塊兒探討學習!
公衆號回覆「面試題」送你一份面試題以及做者的做答答案
每篇文章用到的全部案例代碼素材都會上傳我我的 github
歡迎來踩!