今天聊一聊你们最耳熟能详的设计模式,『工厂模式』。实际上这个设计模式有三个变种,分别是『简单工厂模式』、『工厂方法模式』以及『抽象工厂模式』,可能大部人所熟知的是前两种,抽象工厂模式有必定的场景限制,不多出如今你们的视野中,不过今天咱们一并谈一谈。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
欢迎来踩!