工厂模式
工厂模式,对于大部分的开发者来讲,可能并不陌生,但是可能并非所有人都能完全理解,尤其是对于初学者。有的初学者经常会问:
工厂模式有什么用?有什么好处?什么时候用工厂模式?
网络上也有很多解答,诸如:可以更好的封装、模块化、还有的书上写着在生成复杂对象的地方,可以使用工厂模式
。那么如何衡量一个对象的复杂的?这些解释都是对的,但是对于一个初学者并不好理解。
对于初学者,最大的疑惑可能就在于:通过工厂create
出来的对象和new
出来的对象相比,优势在哪里?直接new
不就好了吗,还要写个工厂类这么麻烦?
笔者也是一直处于学习过程,梳理了一下工厂模式的使用场景和解决的痛点,通俗的聊一聊,如有错误,欢迎指正!
抛开前面抽象的定义,举一个通俗的例子,带你自然而然的应用上工厂设计模式。
某团队有如下两位开发人员:
- 移动端 : 小张
- 算法 : 小李
小张负责终端应用的开发,小李根据具体的业务逻辑写一些算法,封装成SDK提供给小张使用。
某天,产品提出了需求,需要开发某功能,算法小李根据需求,封装了一个类,提供了一个1.0版本的SDK给终端小张使用。具体如下
public class FunctionA{
public void method(){
// 业务逻辑
}
}
小张可以在程序里直接调用方法而不用管小李是如何实现的
FunctionA functionA = new FunctionA();
functionA.method();
两人各司其职,合作非常愉快。如果你也觉得,恩,他们配合的不错,那么你可以继续往下看。
直到有一天,产品又提出了新的需求,以前的算法逻辑不用了,有了新的逻辑。
算法小李最开始想到的就是,OK,改一下FunctionA
的method()
方法,改为新的。但是小李一想,如果某一天万恶的产品又要改回去怎么办?想想不行,之前的算法不能删,于是乎,算法小李又重新定义了一个类,实现了第二套业务逻辑,生成了1.1版本的SDK给终端小张使用,果然高明。
public class FunctionB{
public void method(){
// 新的业务逻辑
}
}
终端小张收到算法小李给的SDK以后发现,根据需求,以前的FunctionA
不能再用了,于是乎,终端小张也开始改程序,使用FunctionB
FunctionB functionB = new FunctionB();
functionB.method();
终端小张开始有点不爽,你改你的算法,和我有什么关系?增加我的工作量!
(试想一下,如果你使用了某第三方SDK,SDK每次更新,你在本地都要改代码,是不是得疯掉?)
产品又来了,改改改……
改了好多次,小张和小李打了起来……
算法小李应该怎样做,可以避免这种情况?这里就可以使用到工厂方法。
算法FunctionA
和算法FunctionB
都是为了实现同一个功能,只不过实现过程不一样。
终端小张想要的是:
你改你的算法,你改完算法,我可以替换新的SDK,但是不要影响到我本地的程序。
我只要调用
function.method();
就好了。
我不管你function
是算法A还是算法B。
那么,这里小张想要的function
就涉及到了Java的多态了,它即可能是FunctionA
也可能是FunctionB
。
算法小李就可以这样改,定义一个抽象的Function
,有一个抽象的method()
方法,然后让算法FunctionA
和算法FunctionB
都继承Function
,分别实现method()
方法。
像这样
Function
public abstract class Function {
public abstract void method();
}
FunctionA
public class FunctionA extends Function {
@Override
public void method() {
// 算法A的实现
}
}
FunctionB
public class FunctionB extends Function {
@Override
public void method() {
// 算法B的实现
}
}
然后再提供一个工厂类,可以返回一个多态的Function
对象
public class FunctionFactory {
public static Function createFunction() {
return new FunctionB();
}
}
这样一来,终端小张爽了,可以通过工厂获取Function
Function function = FunctionFactory.createFunction();
function.method();
以后算法不管怎样改,他都不需要再担心,如果产品再想改算法,算法小李只需要再定义一个FunctionC
,在createFunction
方法里返回即可。
这也体现了为什么说工厂模式是依赖于抽象架构的,他们都有属于一类事物,都有相同的方法,只是实现不同,由此可见,通过工厂模式,可以实现解耦
,对于算法小李,还有一定的可扩展性
。
又有一天,产品又来新需求了,希望用户可以自己选择使用哪种逻辑算法。
终端小张希望可以提供相应接口,对应提供不同的逻辑。
算法小李首先想到的就是再多写几个create方法,诸如createFunctionA(),createFunctionB()……
虽然不是不行,但是假如你有成百上千套算法,难道要写成百上千个create方法么,这显然是码农的做法,作为工程师,我想只用一个方法,指哪打哪,要啥给啥!这就用到了反射。
可以这样实现
FuncFactory
public abstract class FuncFactory {
public abstract <T extends Function> T createFunction(Class<T> clz);
}
FunctionFactory
public class FunctionFactory extends FuncFactory {
@Override
public <T extends Function> T createFunction(Class<T> clz) {
Function function = null;
try {
function = (Function) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) function;
}
}
这样一来,终端小张就可以尽情玩耍了,
想用A算法,就传一个FunctionA
FuncFactory factory = new FunctionFactory();
Function function = factory. createFunction(FunctionA.class);
想用算法B,就传一个FunctionB
FuncFactory factory = new FunctionFactory();
Function function = factory. createFunction(FunctionB.class);
这里用到了抽象工厂类FuncFactory
,同样也是为了方便扩展,现在小张和小李只用到了一种逻辑,可有可无,如果以后还有多种逻辑要实现,可以在抽象工厂里添加对应的create方法,方便扩展。
简单的理解到这里,欢迎指正!