Java设计模式(二) 工厂方法模式
本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则
原创文章。同步自[作者个人博客](http://www.jasongj.com/design_pattern/factory_method/) [http://www.jasongj.com/design_pattern/factory_method/](http://www.jasongj.com/design_pattern/factory_method/)
工厂方法模式解决的问题
上文《简单工厂模式不简单》中提到,简单工厂模式有如下缺点,而工厂方法模式可以解决这些问题
- 由于工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连。
- 由于简单工厂模式的产品是基于一个共同的抽象类或者接口,这样一来,产品的种类增加的时候,即有不同的产品接口或者抽象类的时候,工厂类就需要判断何时创建何种接口的产品,这就和创建何种种类的产品相互混淆在了一起,违背了单一职责原则,导致系统丧失灵活性和可维护性。
- 简单工厂模式违背了“开放-关闭原则”,因为当我们新增加一个产品的时候必须修改工厂类,相应的工厂类就需要重新编译一遍。
- 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
工厂方法模式
工厂方法模式介绍
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫多态工厂模式或者虚拟构造器模式。在工厂方法模式中,工厂父类定义创建产品对象的公共接口,具体的工厂子类负责创建具体的产品对象。每一个工厂子类负责创建一种具体产品。
工厂方法模式类图
工厂模式类图如下 (点击可查看大图)

工厂方法模式角色划分
- 抽象产品(或者产品接口),如上图中IUserDao
- 具体产品,如上图中的MySQLUserDao,PostgreSQLUserDao和OracleUserDao
- 抽象工厂(或者工厂接口),如IFactory
- 具体工厂,如MySQLFactory,PostgreSQLFactory和OracleFactory
工厂方法模式使用方式
如简单工厂模式直接使用静态工厂方法创建产品对象不同,在工厂方法,客户端通过实例化具体的工厂类,并调用其创建实例接口创建具体产品类的实例。根据依赖倒置原则,具体工厂类的实例由工厂接口引用(客户端依赖于抽象工厂而非具体工厂),具体产品的实例由产品接口引用(客户端和工厂依赖于抽象产品而非具体产品)。具体调用代码如下
package com.jasongj.client;
import com.jasongj.dao.IUserDao;
import com.jasongj.factory.IDaoFactory;
import com.jasongj.factory.MySQLDaoFactory;
public class Client {
public static void main(String[] args) {
IDaoFactory factory = new MySQLDaoFactory();
IUserDao userDao = factory.createUserDao();
userDao.getUser("admin");
}
}
工厂方法模式示例代码
本文所述工厂方法模式示例代码可从作者Github下载
工厂方法模式优点
- 因为每个具体工厂类只负责创建产品,没有简单工厂中的逻辑判断,因此符合单一职责原则。
- 与简单工厂模式不同,工厂方法并不使用静态工厂方法,可以形成基于继承的等级结构。
- 新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可,相比于简单工厂模式需要修改判断逻辑而言,工厂方法模式更符合开-闭原则。
工厂方法模式缺点
- 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
- 虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要换用另外一种产品,仍然需要修改实例化的具体工厂。
- 一个具体工厂只能创建一种具体产品
简单工厂模式与OOP原则
已遵循的原则
- 依赖倒置原则
- 迪米特法则
- 里氏替换原则
- 接口隔离原则
- 单一职责原则(每个工厂只负责创建自己的具体产品,没有简单工厂中的逻辑判断)
- 开闭原则(增加新的产品,不像简单工厂那样需要修改已有的工厂,而只需增加相应的具体工厂类)
未遵循的原则
- 开闭原则(虽然工厂对修改关闭了,但更换产品时,客户代码还是需要修改)
Java设计模式系列
- Java设计模式(一) 简单工厂模式不简单
- Java设计模式(二) 工厂方法模式
- Java设计模式(三) 抽象工厂模式
- Java设计模式(四) 观察者模式
- Java设计模式(五) 组合模式
- Java设计模式(六) 代理模式 VS. 装饰模式
- Java设计模式(七) Spring AOP JDK动态代理 vs. cglib
Java设计模式(二) 工厂方法模式的更多相关文章
- java设计模式(二)---工厂方法模式
2普通工厂方法模式 就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建. 2.1创建接口 /** * 发送接口 * Created by mrf on 2016/2/25. */ public ...
- Java设计模式之工厂方法模式(转) 实现是抽象工厂?
Java设计模式之工厂方法模式 责任编辑:覃里作者:Java研究组织 2009-02-25 来源:IT168网站 文本Tag: 设计模式 Java [IT168 技术文章] ...
- Java设计模式系列-工厂方法模式
原创文章,转载请标注出处:<Java设计模式系列-工厂方法模式> 一.概述 工厂,就是生产产品的地方. 在Java设计模式中使用工厂的概念,那就是生成对象的地方了. 本来直接就能创建的对象 ...
- Java设计模式 之 工厂方法模式
1. 使用设计模式的好处:可提高代码的重复性,让代码更容易被他人理解,保证代码的可靠性. 2. 工厂模式定义:就是创建一个工厂类来创建你需要的类,工厂模式包括工厂模式和抽象工厂模式,抽象工厂模式是工厂 ...
- JAVA设计模式之工厂方法模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述工厂方法模式的: 工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymor ...
- Java 设计模式(四)-工厂方法模式 (FactoryMethod Pattern)
1 概念定义 1.1 定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 1.2 类型 创建类模式 2 原理特征 2.1 类 ...
- 【java】 java 设计模式(1):工厂方法模式(Factory Method)
工厂方法模式分为三种: 1.普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建.首先看下关系图: 举例如下:(我们举一个发送邮件和短信的例子) 首先,创建二者的共同接口: p ...
- Java设计模式(2)——工厂方法模式
工厂方法模式同样属于类的创建型模式又被称为多态工厂模式.工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色, ...
- java设计模式学习 ----- 工厂方法模式(Factory Method)
工厂方法模式(Factory Method) 工厂方法模式分为三种:普通工厂模式.多个工厂方法模式.静态工厂方法模式 普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建. 关系图 ...
- 设计模式(二)—工厂方法模式
凡是出现了大量的实例需要创建,而且具有共同的接口时,可以通过工厂方法模式进行创建. 一个接口: Sender public interface Sender{ public void sen ...
随机推荐
- Java日志规范
前言 一个在生产环境里运行的程序如果没有日志是很让维护者提心吊胆的,有太多杂乱又无意义的日志也是令人伤神.程序出现问题时候,从日志里如果发现不了问题可能的原因是很令人受挫的.本文想讨论的是如何在Jav ...
- 转: Hibernate commit() 和flush() 的区别
[java] view plaincopyprint? <<精通Hibernate java对象持久化技术详解>> ,flush()方法进行清理缓存的操作,执行一系列的SQL语 ...
- Ubuntu下Nutch1.2的使用
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeMAAABpCAIAAACGSdxlAAAAA3NCSVQICAjb4U/gAAAgAElEQVR4Xu ...
- 使用Javascript中变量的setter属性
在讲JDK的动态代理方法之前,不妨先想想如果让你来实现一个可以任意类的任意方法的代理类,该怎么实现?有个很naive的做法,通过反射获得Class和Method,再调用该方法,并且实现一些代理的方法. ...
- SQL疑难问题
最近,遇到并解决一个SQL上的疑难问题.考勤系统,记录着员工进出公司的刷卡记录.而员工刷卡并不规范,存在刷多次的情况.例如:出去时连续刷多次,进来时也连续刷多次.筛选有效刷卡记录数据的规则:对于出去时 ...
- IE关闭兼容性视图
不知道什么时候,ie8的“兼容性视图设置”变成了灰色,如图: 今天通过设置组策略,终以解决了这个问题: ie8的兼容性视图设置灰色的解决办法:运行gpedit.msc--用户配置/计算机配置--管理 ...
- java.lang.Boolean->介绍
介绍: public class Boolean extends Object implements Serializable, Comparable<Boolean> Boolean类是 ...
- python 中的高级函数reduce()
reduce()函数也是Python内置的一个高阶函数.reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收 ...
- jQuery--事件总结
标准的绑定: bind(type,[,data],fn)==>第一个参数是事件类型 第二个可选参数作为event.data 传递给事件对象的额外数据对象 第三个参数为用来绑定的处理函数 简写绑定 ...
- 【kate整理】matlab求商,求余数
a/b=q...r a=b*q+r r为余数 fix(a/b) 求商rem(a,b) 求余数还可以 mod(a,b) 两者的区别是余数的符号,rem与a相同,而mod与b相同 例1: & ...