写在前面的话:

   虽然在我们的日常开发过程中,不用设计模式也可以完成相应的功能,但是用好的设计模式可以帮助我们更好的解决实际问题,设计模式一个重要的思想是解耦,降低代码间的粘着性。几乎我们所有的java框架和源码都使用了良好的设计模式,比如spring就使用了诸如BeanFactory的工厂模式,mybatis框架的模板模式等等。学习设计模式可以更好的让我们把业务转化成技术实现。

   工厂模式从名字上来看,脱离于现实生活中的工厂,就是生成和制造各种产品的,比如口罩工厂。在Java的世界里,工厂模式,也是同样的道理,也是用来生产东西的(类实例对象)。在没有该模式的情况下,我们一般生产对象(创建对象)一般都是采用new的形式。那为什么有了new的方式,还要提出一种“工厂模式”呢?原因其实还是比较容易理解,就比如这个生产口罩的工厂内部,口罩分多钟型号,KN94/KN95/KF94等等。假如一个公民想要买口罩,我得告诉工厂我要哪种型号的吧,然后它生产出来给我。但生产某种型号的过程我是不知道的,不知道用了什么材料,不知道用了什么工艺对吧? 然后反过来想new的这种方式,一般代码为KouZhao​​ kouZhao = new ​​​KouZhao​​()​​,使用new 的前提是什么?得先知道KouZhao这个类吧,也就是说我得知道KouZhao是要用什么材料用什么工艺来做的,工厂模式就是 将这个过程隐藏起来只给结果给调用方。

1.简单工厂模式

  简单工厂就是我给你型号,你帮我生产,隐藏生产过程。new是我自己知道这个型号的制作过程和原理,自己申明生产过程。就 是传入一个型号名称(形参),内部if-else去判断生产对象型号名称的口罩。如果要新增型号,只能修改该工厂内部的if-else语句,新增判断。

常用的设计模式之工厂模式_设计模式

KouZhaoFactory factory = new KouZhaoFactory();
KN94KouZhao kn94 = (KN94KouZhao) factory.create("KN94");
KN95KouZhao kn95 = (KN95KouZhao) factory.create("KN95");
KF94KouZhao kf94 = (KF94KouZhao) factory.create("KF94");
kn94.protect();
kn95.protect();
kf94.protect();

为了避免字符串写错造成的问题可以使用反射改进一下:

常用的设计模式之工厂模式_抽象工厂模式_02


KouZhaoFactory代码如下:
KouZhao create(Class <? extends  KouZhao> clazz){
try {
if (clazz!=null) {
return clazz.newInstance();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

 测试方法如下:

KouZhaoFactory factory = new KouZhaoFactory();
KN94KouZhao kn94 =(KN94KouZhao) factory.create(KN94KouZhao.class);
KN95KouZhao kn95 =(KN95KouZhao) factory.create(KN95KouZhao.class);
KF94KouZhao kf94 =(KF94KouZhao) factory.create(KF94KouZhao.class);
kn94.protect();
kn95.protect();
kf94.protect();

从上面可以看出简单工厂模式中工厂类的职责相对过重,所有的判断和创建都在内部完成,不易于扩展过于复杂的产品结构。

2.工厂方法模式

    简单工厂模式看起来像一个万能工厂啥型号的口罩都可生成,工厂类的职责过重了,工厂方法模式是对简单工厂进行了升级,不在由工厂类生成具体的口罩了,而是产生一个抽象的口罩接口,我们先创建一个口罩接口,再创建KN94、KN95、KF94实现类实现口罩接口。在使用时,直接给工厂传入指定的实现类,内部利用反射的机制,绑定创建好指定型号(类型)的口罩。类图如下:

常用的设计模式之工厂模式_设计模式_03

测试代码:


KouZhaoFactory factory = new KN94KouZhaoFactory();
KouZhao kn94 = factory.create();
kn94.protect();

KouZhaoFactory factory2 = new KN95KouZhaoFactory();
KouZhao kn95 = factory2.create();
kn95.protect();

KouZhaoFactory factory3 = new KF94KouZhaoFactory();
KouZhao kf94 = factory3.create();
kf94.protect();

从上面可以看出工厂方法模式中类的过多比简单工厂模式几乎多了1倍,系统的复杂度也随之增加,理解起来不是那么容易。

3.抽象工厂模式

现实中一个工厂很少只生成1中产品的,通常情况都是如下图所示:

常用的设计模式之工厂模式_工厂模式_04

我们将1个工厂相同颜色的各种产品称作1个产品族,不同工厂的相同产品称作1个产品等级结构,即上图中的x轴和y轴。

在我们java世界里抽象工厂模式源于此, 抽象工厂模式是工厂方法的升级。假设现在用户想要购买口罩了,突然又想买点绷带备用,如果没有这个产品就很尴尬了,使用抽象工厂可以给用户更多的选择。类图如下:

常用的设计模式之工厂模式_设计模式_05

测试代码:

KouZhaoFactory factory = new KN94KouZhaoFactory();
factory.createBengDai().blood();
factory.createHuMuJing().protectEyes();
factory.createKouZhao().protect();


KouZhaoFactory factory2 = new KN95KouZhaoFactory();
factory2.createBengDai().blood();
factory2.createHuMuJing().protectEyes();
factory2.createKouZhao().protect();

KouZhaoFactory factory3 = new KF94KouZhaoFactory();
factory3.createBengDai().blood();
factory3.createHuMuJing().protectEyes();
factory3.createKouZhao().protect();

总结:抽象工厂模式可以完美的展现出产品族和产品等级的关系,适用于产品数量不多的情况,过多的产品会使系统复杂度成倍递增。