今天聊一聊大家最耳熟能详的设计模式,『工厂模式』。实际上这个设计模式有三个变种,分别是『简单工厂模式』、『工厂方法模式』以及『抽象工厂模式』,可能大部人所熟知的是前两种,抽象工厂模式有一定的场景限制,很少出现在大家的视野中,不过今天我们一并谈一谈。
简单工厂模式
简单工厂说白了就是一个超级工厂,他可以生产各种各样的产品,产品之间无关联,比如:
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();
}
}
这就是一个简单工厂模式,非常的简单,还没有很强的抽象性。
Spring 的 BeanFactory 其实就是一个简单工厂模式,他定义了一个 BeanFactory 工厂,然后会有 DefaultListableBeanFactory 去实现这个工厂声明的所有能力。
工厂方法模式
其实理论上来说,可以把简单工厂模式理解为工厂方法模式的一种特例,将他的那个超级大工厂拆分成多个工厂就是工厂方法模式了。
同样有一个抽象接口表述一个工厂:
public interface MethodFactory {
//生产一个冰箱
Refrigerator createRefiger();
//生产一个空调
AirConditioning createAirConditioning();
//生产一个 TV
TV createTV();
}
简单工厂是用一个 DefaultFactory 完成了工厂所有的能力要求。但是现在我们的厂家变多了,有格力冰箱、海尔冰箱、海信冰箱等等,他们生产的冰箱或空调都不一样,如果用简单工厂的话,就需要做区分,增加更多的方法,生产格力冰箱的,生产海尔冰箱的,非常的丑陋。
工厂方法模式,需要区分不同的工厂,这里我们创建格力工厂、海尔工厂和海信工厂。
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();
}
}
格力工厂返回的是格力的空调、格力的冰箱以及格力的电视机,海尔和海信也都会返回他们自己品牌的产品,这里就不贴他们的代码了,类似。
这样,我们的工厂方法对外提供了生产产品的能力,具体产生何种类型的产品,将由具体的工厂决定。这就是工厂方法模式,相信大部分人应该都不陌生。
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
https://github.com/SingleYam/overview_java
欢迎来踩!