工厂模式分为简单工厂模式,工厂方法模式,抽象工厂模式。属于创建型模式
**
简介:平常创建对象都是直接new对象,如果创建对象需要关联一系列操作,我们一般会在构造方法里关联这些操作;但是操作比较多、复杂,会使得构造方法很长降低可读性。这时不妨创建一个工厂类专门负责对象的创建;

工厂模式的基本逻辑

假设我们的业务代码当中,有一个被广泛引用的“口罩类”,这个类实例需要在许多地方被创建和初始化,而初始化的代码也比较复杂

  1. public class Mask { //口罩类
  2. public Mask(){ //构造方法
  3. //.... // 100行初始化代码
  4. }
  5. }

针对这种情况,我们可以构建一个“口罩工厂”专门负责创建口罩对象,把口罩类的初始化代码迁移到工厂类的创建方法当中:

  1. public class MaskFactory { //口罩工厂
  2. public Mask createMask() { //返回口罩类对象的方法
  3. Mask mask = new Mask();
  4. // .....
  5. // 100行初始化代码
  6. return mask;
  7. }
  8. }

简单工厂模式

简单工厂模式有唯一的工厂类,工厂类的创建方法根据传入的参数做if-else条件判断,决定最终创建什么样的产品对象。
工厂类创建对象,工厂类根据传入参数决定具体子类对象

接上,假如口罩类更加复杂(存在子类),我们可以给工厂类创建对象加上一系列条件判断
假设口罩类分为2个子类。分别是高端口罩和低端口罩,我们可以把口罩类Mask转变为接口

  1. public interface Mask {
  2. void show();
  3. }
  4. public class HighEndMask implements Mask {
  5. @Override
  6. public void show() {
  7. System.out.println("我是高端口罩");
  8. }
  9. }
  10. public class LowEndMask implements Mask {
  11. @Override
  12. public void show(){
  13. System.out.println("我的低端口罩");
  14. }
  15. }

在口罩工厂的创建方法中传入参数(这里的参数是type),根据参数来做条件判断,决定创建什么样的口罩:

  1. public class MaskFactory{
  2. public Mask createMask(String type) {
  3. Mask mask = null;
  4. if("高端口罩".equals(type)){
  5. mask = new HighEndMask();
  6. // 高端口罩HighEndMask的100行初始化代码
  7. }else if("低端口罩".equals(type)){
  8. mask = new LowEndMask();
  9. // 低端口罩LowEndMask的100行初始化代码
  10. }
  11. return mask;
  12. }
  13. }

**


工厂方法模式

接上简单工厂模式,如果需要增加新的类型的口罩。就需要增加新的if-else条件判断。不符合面向对象的开放-封闭原则。
要避免“修改原有代码增加新的条件判断”,可以为每一个口罩子类创建相应的口罩工厂。 工厂子类分别实现抽象的工厂方法

所谓的开放-封闭原则,就是在面向对象程序中对“扩展”开放,对“修改”封闭。如果每次业务改动都要对旧有代码修改,不但容易出错,可读性也不好。
(即便没有更改一个类的原有代码,只是增加新的方法,之类的也算是破坏了封闭原则)

修改的代码

  1. public interface MaskFactory {
  2. Mask createMask();
  3. }
  4. public class HighEndFactory implements MaskFactory{
  5. @Override
  6. public Mask createMask() {
  7. Mask mask = new HighEndMask();
  8. // HighEndMask的100行初始化代码
  9. return mask;
  10. }
  11. }
  12. public class LowEndFactory implements MaskFactory{
  13. @Override
  14. public Mask createMask() {
  15. Mask mask = new LowEndMask();
  16. // LowEndMask的100行初始化代码
  17. return mask;
  18. }
  19. }

Test代码

  1. public class Test {
  2. public static void main(String[] args) {
  3. MaskFactory factoryA = new LowEndFactory();
  4. MaskFactory factoryB = new HighEndFactory();
  5. Mask maskA = factoryA.createMask();
  6. Mask maskB = factoryB.createMask();
  7. maskA.show();
  8. maskB.show();
  9. }
  10. }

**

抽象工厂模式

本质:**把产品类从另外一种分类方式分组实现不同产品对应同一工厂类的不同方法
如果需要创建的子类越来越多,不只有口罩类,还有防毒面具,防护服之类的,按照上面的办法每一种子类都要有一个对应的工厂类。显然太繁琐,这时抽象工厂模式可以解决**
假设业务中需要创建口罩、防毒面具、防护服这三种产品,而每一种产品有包含高端和低端两类,按照工厂方法模式的解决方案,需要创建的类如下:

工厂模式 - 图1

转化为以下分类

如果待创建的产品非常多,可以
从另外一种角度对产品进行分组,** 比如直接分为高端产品组和低端产品组,就由很多种产品转为只有2种产品(高端-低端)

工厂模式 - 图2

  1. public interface Mask {
  2. void showMask();
  3. }
  4. public class LowEndMask implements Mask {
  5. @Override
  6. public void showMask(){
  7. System.out.println("我的低端口罩");
  8. }
  9. }
  10. public class HighEndMask implements Mask {
  11. @Override
  12. public void showMask() {
  13. System.out.println("我是高端口罩");
  14. }
  15. }
  16. public interface ProtectiveSuit { //防护服接口
  17. void showSuit();
  18. }
  19. public class LowEndProtectiveSuit implements ProtectiveSuit {
  20. @Override
  21. public void showSuit() {
  22. System.out.println("我是低端防护服");
  23. }
  24. }
  25. public class HighEndProtectiveSuit implements ProtectiveSuit {
  26. @Override
  27. public void showSuit() {
  28. System.out.println("我是高端防护服");
  29. }
  30. }
  31. //工厂类:另外一种分组方式
  32. public interface Factory {
  33. //创建口罩
  34. Mask createMask();
  35. //创建防护服
  36. ProtectiveSuit createSuit();
  37. }
  38. public class LowEndFactory implements Factory {
  39. @Override
  40. public Mask createMask() {
  41. Mask mask = new LowEndMask();
  42. // LowEndMask的100行初始化代码
  43. return mask;
  44. }
  45. @Override
  46. public ProtectiveSuit createSuit() {
  47. ProtectiveSuit suit = new LowEndProtectiveSuit();
  48. // LowEndProtectiveSuit的100行初始化代码
  49. return suit;
  50. }
  51. }
  52. public class HighEndFactory implements Factory {
  53. @Override
  54. public Mask createMask() {
  55. Mask mask = new HighEndMask();
  56. // HighEndMask的100行初始化代码
  57. return mask;
  58. }
  59. @Override
  60. public ProtectiveSuit createSuit() {
  61. ProtectiveSuit suit = new HighEndProtectiveSuit();
  62. // HighEndProtectiveSuit的100行初始化代码
  63. return suit;
  64. }
  65. }
  66. //Test代码:通过实例化不同的工厂子类,调用不同的创建方法,可以创建出不同的产品:
  67. public class Test {
  68. public static void main(String[] args) {
  69. Factory factoryA = new LowEndFactory();
  70. Factory factoryB = new HighEndFactory();
  71. //创建低端口罩
  72. Mask maskA = factoryA.createMask();
  73. //创建高端口罩
  74. Mask maskB = factoryB.createMask();
  75. //创建低端防护服
  76. ProtectiveSuit suitA = factoryA.createSuit();
  77. //创建高端防护服
  78. ProtectiveSuit suitB = factoryB.createSuit();
  79. maskA.showMask();
  80. maskB.showMask();
  81. suitA.showSuit();
  82. suitB.showSuit();
  83. }
  84. }

简单工厂模式,工厂方法模式的Test也是类似的


总结

  • 简单工厂模式:

简单工厂模式有唯一的工厂类,工厂类的创建方法根据传入的参数做if-else条件判断,决定最终创建什么样的产品对象。

  • 工厂方法模式:

工厂方法模式由多个工厂类实现工厂接口,利用多态来创建不同的产品对象,从而避免了冗长的if-else条件判断。**

  • 抽象工厂模式:

抽象工厂模式把产品子类进行分组,同组中的不同产品由同一个工厂子类的不同方法负责创建,从而减少了工厂子类的数量。

抽象工厂模式把产品子类进行分组,同组中的不同产品由同一个工厂子类的不同方法负责创建,从而减少了工厂子类的数量。

工厂模式 - 图3
工厂模式 - 图4
工厂模式 - 图5
工厂模式 - 图6
熟悉spring框架的小伙伴,一定知道spring的一个重要特性:依赖注入(DI)
通过spring的依赖注入,开发人员不需要在业务代码中手动实例化bean对象,也不需要知道任何工厂类。

bean对象从创建到销毁的整个过程,完全交给spring容器来管理,用户需要做的仅仅是在xml配置文件中(或使用注解)设置bean的各项属性:

  1. <bean id="userController" class="com.xiaohui.controller.UserController">
  2. <constructor-arg name="userService" ref="userService"></constructor-arg>
  3. </bean>
  4. <bean id="userService" class="com.xiaohui.service.UserService">

根据上面的配置,spring容器会动态创建UserController对象,并创建UserController所依赖的UserService对象。

如果开发人员希望把userService这个bean对象的实现类换成另一个类,并不需要改动任何代码,只需要修改配置文件中对应bean的class属性即可。

spring通过反射

在大多数情况下,我们使用new关键字创建对象,对象所属的class是在代码中明确定义好的。

但是在少数情况下,我们需要借助class的元信息(比如完整类名),在程序运行期间动态创建对象,这就用到了Java的反射。

当我们在spring配置文件中配置了相应的bean,启动项目,spring会为我们解析xml配置文件,并根据bean的不同生命周期,由spring内部的“工厂”创建出bean对象。

对spring依赖注入原理有兴趣的小伙伴,可以阅读spring源码中的BeanFactory接口,以及相关的实现类。