一、简介

工厂模式主要是为创建对象提供了接口。工厂模式按照《Java与模式》中的提法分为三类:

  1. 简单工厂模式(Simple Factory)
  2. 工厂方法模式(Factory Method)
  3. 抽象工厂模式(Abstract Factory)

这三种模式从上到下逐步抽象,并且更具一般性。还有一种分类法,就是将简单工厂模式看为工厂方法模式的一种特例,两个归为一类。下面是使用工厂模式的两种情况:

1.在编码时不能预见需要创建哪种类的实例。
2.系统不应依赖于产品类实例如何被创建、组合和表达的细节 。

二、简单工厂模式(Simple Factory)

顾名思义,这个模式本身很简单,而且使用在业务较简单的情况下。
它由三种角色组成(关系见下面的类图):

1、工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。

2、抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。

3、具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

类图如下:

使用简单工厂模式来实现一个实例:

用面向对象语言实现一个计算机控制台程序:(以java为例)

UML类图如下:

源代码如下:

Operation.java

package com.caculate;public class Operation {protected double numberA=0;protected double numberB=0;public double getNumberA() {return numberA;}public void setNumberA(double numberA) {this.numberA = numberA;}public double getNumberB() {return numberB;}public void setNumberB(double numberB) {this.numberB = numberB;}public double getResult(){double result=0;return result;}
}

OperationAdd.java(加法类)

package com.caculate;
/***加法类*/
public class OperationAdd extends Operation{public double getResult() {double result=0;result=numberA + numberB;return result;}
}

OperationSub.java(减法类)

package com.caculate;
/***减法类*/
public class OperationSub extends Operation{public double getResult() {double result=0;result=numberA - numberB;return result;}
}

OperationMul.java(乘法类)

package com.caculate;
/***乘法类*/
public class OperationMul extends Operation{public double getResult() {double result = 0;result=numberA * numberB;return result;}
}

OperationDiv.java(除法类)

package com.caculate;
/***除法类*/
public class OperationDiv extends Operation{public double getReault() {double result=0;result=numberA/numberB;return result;}
}

OperationFactory.java(工厂类,用来实例化需要用到的运算类对象)

package com.caculate;
/***构建一个工厂类来实例化对象*/
public class OperationFactory {/*** @param operate 传入一个操作符* @return 返回一个对应该操作数的Operation类对象*/public static Operation createOperate(String operate){Operation oper=null;int n=0;if (operate.equals("+")) {n=1;}if (operate.equals("-")) {n=2;}if (operate.equals("*")) {n=3;}if (operate.equals("、")) {n=4;}/**注意:* JRE1.7以下的版本中,switch的判断条件必须是一个int型值,也可以是byte、short、char型值;* 在1.7增加新特性能传string类型*/switch (n) {case 1:oper=new OperationAdd();//如果传入的操作符是+,则实例化一个加法类对象break;case 2:oper=new OperationSub();//如果传入的操作符是-,则实例化一个减法类对象break;case 3:oper=new OperationMul();//如果传入的操作符是*,则实例化一个乘法类对象break;case 4:oper=new OperationDiv();//如果传入的操作符是/,则实例化一个除法类对象break;}return oper;}
}

Test.java(测试类)

package com.caculate;public class Test {public static void main(String[] args) {Operation oper=OperationFactory.createOperate("+");oper.numberA=1;oper.numberB=4;double result=oper.getResult();System.out.println(result);}
}

运行结果: 5.0

总结:

1、当我们需要修改相应的运算时,只需要修改相应的实现类(加减乘除等的实现);当需要增加其他的复杂运算(比如:平方根,立方根等)时,只需要实现相应的运算(既增加运算类的子类),然后增加运算类工厂中的switch分支即可;在使用的时候,只需要输入运算符号,工厂类就能实例化出合适的对象,通过多态,返回父类的方式来实现计算器的结果,而使用者无需了解具体的实现过程,充分契合了面向对象继承、封装和多态的特性。

2、使用了简单工厂模式后,我们的程序更加符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责”消费”产品。

我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以实现起来会很麻烦。所以简单工厂模式适用于业务较简单的情况下。而对于复杂的业务环境可能不太适应。这就应该由工厂方法模式来出场了。

三、工厂方法模式(Factory Method)

简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是,如果我们要加一个“求M数的N次方的功能”,我们是一定需要给运算工厂类的方法里加“case”分支条件的,这就修改了原来的类,就等于我们不但对扩展开放了,也对修改开放了,违背了开放-封闭原则

于是,工厂方法模式就来了。

工厂方法模式(Factory Method)定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

工厂方法模式结构图如下:

还是以上面的计算器为例子,既然这个工厂类与分支耦合,那么我们就对它下手,根据依赖倒转原则,我们把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有的要生产具体类的工厂,就去实现这个接口。这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生成对象的工厂,于是我们增加“求M数的N次方”的功能时,就不需要更改原有的工厂类,只需要增加此功能的运算类和相应的工厂类就可以了。

这样,整个工厂和产品体系都没有修改的变化而只是扩展的变化,这就完全符合开放-封闭原则的精神,同时又保持了封装对象创建过程的优点,降低了客户端与产品对象的耦合。

另外,工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂方法的内部逻辑判断移到了客户端代码来进行。如果想要增加功能,本来是改工厂类,而现在是修改客户端。

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。但还存在不足,就是由于每增加一个产品,就需要增加一个产品工厂的类,增加了额外的开发量。这样,又有一个问题抛出来了,还有没有可以避免修改客户端的实现方法呢?

四、抽象工厂模式(Abstract Factory)

以一个简单的数据库访问程序来系统学习抽象工厂模式。

首先,我们结合上面刚学到的工厂方法模式来实现这个数据库访问程序,类图如下:

客户端代码:

public static void main(String[] args) {User user = new User();IFactory factory = new SqlServerFactory();//数据库为sqlserver时//IFactory factory = new AccessFactory();//数据库为access时IUser iu = factory.createUser();iu.insert(user);//插入用户iu.getUser(1);//得到ID为1的用户Console.Read();}

如果要换数据库,我们只需要把new SqlServerFactory()改为new AccessFactory(),此时由于多态的关系,使得声明IUser接口的对象iu事先根本不知道是在访问哪个数据库,却可以在运行时很好的完成工作,这就是所谓的业务逻辑与数据库操作解耦。

如果我们在数据库中增加一个Department(部门表),就涉及到解决这种涉及到多个产品系列的问题,那么,抽象工厂模式就可以粉墨登场了。

(IFactory接口下也有一个CreateDepartment()方法,画图时漏掉了)

那么,我们需要在原程序的基础上做如下改动:

1、增加一个Department类;
2、增加一个IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合;
3、增加一个SqlserverDepartment类,用于访问SQL Server的Department;
4、增加一个AccessDepartment类,用于访问Access的Department;
5、IFactory接口是定义一个创建访问Department表对象的抽象的工厂接口,增加CreateDepartment()方法,相应的SqlServerFactory和AccessFactory类都要增加该方法;

客户端代码如下:

public static void main(String[] args) {User user = new User();IFactory factory = new SqlServerFactory();//数据库为sqlserver时//IFactory factory = new AccessFactory();//数据库为access时IUser iu = factory.createUser();iu.insert(user);//插入用户iu.getUser(1);//得到ID为1的用户IDepartment id = factory.createDepartment();id.insert(dept);//插入部门id.getDept(1);//得到ID为1的部门Console.Read();}

抽象工厂模式(Abstract Method),提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。

抽象工厂模式的优点:是易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。我们的设计不能去防止需求的更改,那么我们的理想便是让改动变的最小,现在如果你要更改数据库访问,我们只需要更改具体工厂就可以做到。第二大好处是它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。

抽象工厂模式缺点:虽然抽象工厂模式可以很方便的切换两个数据库访问的代码,但是如果你的需求来自增加功能,比如我们现在要增加项目表Project,就至少需要增加三个类,IProject、SqlserverProject、AccessProject,还需要更改IFactory、SqlserverFactory和AccessFactory才可以完全实现。而且,我们的客户端程序类显然不会只是一个,有很多地方都在使用IUser或者IDepartment,而这样的设计,我们在更改数据库的时候,所有的地方都要发生改动,这么大批量的改动显然是非常糟糕的。

使用简单工厂模式来改进抽象工厂模式

大话设计模式—工厂模式相关推荐

  1. 大话设计模式:工厂模式

    一.什么是工厂模式 给一个创建对象的接口,让其子类决定创建哪个具体对象. 允许接口创建对象,但使用哪个类来创建对象,则是交由子类决定的.工厂模式像是一个工厂群,工厂A生产A产品,工厂B生产B产品,你有 ...

  2. 大话设计模式-工厂模式

    工厂模式 Spring IOC就是使用了工厂模式,对象的创建交给一个工厂去创建. 概念:工厂模式(Factory Pattern)使用一个共同的接口指向新创建的对象. 意图:定义一个创建对象的接口,让 ...

  3. 大话设计模式——工厂模式

    1. 简单工厂模式(Simple Factory Pattern) 简单工厂模式包含三个角色: 抽象产品类:一般为具体产品继承的父类 或者 实现的接口 具体产品类:继承 或 实现 抽象产品类角色,在工 ...

  4. linkin大话设计模式--常用模式总结

    linkin大话设计模式--常用模式总结 一,常用设计模式定义 Abstract Factory(抽象工厂模式):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. Adapter( ...

  5. Java设计模式-工厂模式(3)抽象工厂模式

    在Java设计模式-工厂模式(2)工厂方法模式 我们知道了工厂方法模式解决了简单工厂模式中的缺陷,做到了满足开闭原则,但是时代是进步的,进而又产生新的问题,工厂难道只能生产一种东西吗.我们所见到的工厂 ...

  6. Java设计模式-工厂模式(2)工厂方法模式

    在Java设计模式-工厂模式(1)简单工厂模式 中我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而"工厂方法模式"是对简单工厂模式的进一步抽象化,其好处是可以使系统在不 ...

  7. Java设计模式-工厂模式(1)简单工厂模式

    Java设计模式-工厂模式(1)简单工厂模式 一.前言 1)例子 2)类图关系 3)代码实现 二.简单工厂模式 2.1.概述: 2.2.类图关系: 2.3.代码修改: 2.4.优缺点 2.5.扩展-简 ...

  8. 设计模式---工厂模式

    设计模式---工厂模式 工厂方法模式 概述:工厂方法模式中抽象工厂负责定义创建对象的接口,具体创建工作由继承抽象工厂的具体类实现. 优点:客户端不需要再负责对象的创建,从而明确了各个类的职责,如果有新 ...

  9. java设计模式工厂模式_Java中的工厂设计模式

    java设计模式工厂模式 Welcome to the Factory Design Pattern in Java tutorial. Factory Pattern is one of the C ...

最新文章

  1. java display html_css html布局之display属性_动力节点Java学院整理
  2. memcache函数整理
  3. Google和Baidu常用的搜索技巧--转
  4. react中弹框的显示隐藏
  5. 邪恶的Java技巧使JVM忘记检查异常
  6. 训练日志 2018.10.11
  7. UNIGUI接收普通消息和被动回复用户消息
  8. 计算机网络——计算机网络病毒和黑客
  9. 怎么卸载mysql_mysql卸载教程,教你如何彻底卸载MySQL数据库软件(亲测成功)
  10. 《REWORK》读记
  11. python虚拟机管理系统_python 虚拟机 pdf
  12. Yii2中如何使用CodeCeption
  13. CMOS相机和CCD相机的区别
  14. 腾讯云服务器8核16G18M配置测评
  15. html5 audio音乐播放,循环播放等9款播放器
  16. 想要在华为云上部署javaweb项目怎么做
  17. 车载以太网解决方案 助力智能网联汽车开发
  18. SDL开发笔记(三):使用SDL渲染窗口颜色和图片
  19. Bootstrap中的utilities(工具类)
  20. 想成为注塑模具设计高手:这个你一定要懂

热门文章

  1. Android 打开网页搜索关键词
  2. Android 顶部滑动切换实现(一)
  3. android String的replace和replaceAll的使用
  4. Java中只有按值传递,没有按引用传递!
  5. ASP.NET Core 中间件(Middleware)详解
  6. 2019-1-15 课后作业
  7. Apache Kylin的核心概念
  8. Python开发【第一篇】:目录
  9. LeetCode:Unique Binary Search Trees
  10. Windows phone msdn 索引