工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
1. 背景
项目需求:开发一个能够拥有加减乘除功能的计算器
技术选型:Java Swing编程
原型图大致如上所示
2. 代码优化
2.1 第一版
加法按钮的后台代码,如下
分析
看完上面的代码,思索如下。
- 图中画红框的地方很明显,就已经写死了,只能获取两个固定组件的值,也只能调用加法,如果我此时需要一个减法的按钮,那么就要把加法的代码粘贴过去,然后修改一下逻辑。
- 那么我需要一个乘法呢?除法呢?或者一个更加高级的算法?,复制粘贴修改虽然是用的比较多的一种方式,但是它的缺点也是很明显的,复制粘贴修改很容易修改出错,而且也不容易理解。
- 更有甚者,当这种加法不满足我的需求,我需要一个高级加法,我就需要去修改加法的代码,这样就违背了开闭原则了。那么怎么优化呢?
另外,如下图,加法和加法逻辑在一起,另外的页面需要加法,也是粘贴过去吗?
抽象
我们可以把加法按钮的方法和加法逻辑拆开,形成类似于现在流行的前后端分离的模式,界面只负责
调用按钮的方法,具体的实现方法由后端提供
按钮方法
封装
加法运算类
这样在其他就把加法运算类抽象出来了,其他加法按钮也就可以调用这个方法了
假如有一天你想把加法按钮的加法运算变成NB加法运算
除了改代码,还有什么选择吗?
先举例说明一下开闭原则的重要性
上述问题就是由于违背开闭原则导致的,修改以前的代码看似没有问题,但是由于这个时候随着代码逻辑越来越复杂,代码耦合性比较强,一旦修改,当前问题可能解决了,但是也很容易导致引发其他问题
从上面对开闭原则的例子我们明白了,为什么不可以违背开闭原则,那么怎么在不修改代码的情况下,才能切换算法呢?
AddOperation addOperation=new AddOperation ();
必须用AddOperation
咱们先解决等号左边的问题,就是先将AddOperation 抽象为运算类,这也叫做依赖抽象
此时增加NB加法运算类,和Operation运算类,此时Operation是父类,其他的运算都去继承他
多态
此时左边就可以切换成Operation operation,由于Operation是父类,根据多态的特性,父类的引用可以指向子类的对象,那么此时等号左边就不需要动了,只要修改等号右边的代码就可以了
反射
但是你可能又要说了,那不是还是修改代码了嘛,不要着急,这个时候我们可以利用反射,通过修改配置文件,就可以实现不修改代码就可以切换运算方法
简单工厂
加入我要制造一辆汽车
你是不是要先new一个汽车类,然后new一个底盘类,然后new一个轮胎类,等等
汽车是要批量化生产的,难道你每次生产汽车都要这么new一遍吗?
但是如果有流水线工厂就不一样的
此时new对象的职责可以交给工厂来办
加法减法等等运算类就可以放到工厂中,你要什么算法由工厂来给你new
此时的UML
但是这个时候有一个问题,简单工厂中有的算法你可以调用,但是没有的呢?
接下来新增一个算法的流程就变成了这样
那有什么办法解决呢?
工厂方法
你比如你想要一个特殊的算法,简单工厂没有办法满足你,工厂方法的解决办法就是给你一个凭据
你需要什么样的工厂都可以调用IFactory工厂
然后看如下代码
增加一个加法工厂实现了工厂接口
Addfactory可以放到配置文件中,此时需要一个什么加法工厂就传进去什么加法工厂就可以了
因为你传的是Addfactory,所以
所以此时的factory.createOperation();调用的就是Addfactory的createOperation的方法,返回的就是加法工厂
这就实现了工厂方法