《JAVA与模式》之工厂方法模式
在阎宏博士的《JAVA与模式》一书中开头是这样描述工厂方法模式的:
工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。
工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
那么工厂方法模式是在什么场景下使用呢,下面就以本人的理解举例说明:
相信很多人都做过导入导出功能,就拿导出功能来说。有这么一个需求:XX系统需要支持对数据库中的员工薪资进行导出,并且支持多种格式如:HTML、CSV、PDF等,每种格式导出的结构有所不同,比如:财务跟其他人对导出薪资的HTML格式要求可能会不一样,因为财务可能需要特定的格式方便核算或其他用途。
如果使用简单工厂模式,则工厂类必定过于臃肿。因为简单工厂模式只有一个工厂类,它需要处理所有的创建的逻辑。假如以上需求暂时只支持3种导出的格式以及2种导出的结构,那工厂类则需要6个if else来创建6种不同的类型。如果日后需求不断增加,则后果不堪设想。
这时候就需要工厂方法模式来处理以上需求。在工厂方法模式中,核心的工厂类不再负责所有的对象的创建,而是将具体创建的工作交给子类去做。这个核心类则摇身一变,成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个类应当被实例化这种细节。
这种进一步抽象化的结果,使这种工厂方法模式可以用来允许系统在不修改具体工厂角色的情况下引进新的产品,这一特点无疑使得工厂方法模式具有超过简单工厂模式的优越性。下面就针对以上需求设计UML图:

从上图可以看出,这个使用的工厂方法模式的系统涉及到以下角色:
抽象工厂(ExportFactory)角色:担任这个角色的是工厂方法模式的核心,任何在模式中创建对象的工厂类必须实现这个接口。在实际的系统中,这个角色也常常使用抽象类实现。
具体工厂(ExportHtmlFactory、ExportPdfFactory)角色:担任这个角色的是实现了抽象工厂接口的具体JAVA类。具体工厂角色含有与业务密切相关的逻辑,并且受到使用者的调用以创建导出类(如:ExportStandardHtmlFile)。
抽象导出(ExportFile)角色:工厂方法模式所创建的对象的超类,也就是所有导出类的共同父类或共同拥有的接口。在实际的系统中,这个角色也常常使用抽象类实现。
具体导出(ExportStandardHtmlFile等)角色:这个角色实现了抽象导出(ExportFile)角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体导出角色的实例。
源代码
首先是抽象工厂角色源代码。它声明了一个工厂方法,要求所有的具体工厂角色都实现这个工厂方法。参数type表示导出的格式是哪一种结构,如:导出HTML格式有两种结构,一种是标准结构,一种是财务需要的结构。
public interface ExportFactory {
public ExportFile factory(String type);
}
具体工厂角色类源代码:

public class ExportHtmlFactory implements ExportFactory{
@Override
public ExportFile factory(String type) {
// TODO Auto-generated method stub
if("standard".equals(type)){
return new ExportStandardHtmlFile();
}else if("financial".equals(type)){
return new ExportFinancialHtmlFile();
}else{
throw new RuntimeException("没有找到对象");
}
}
}


public class ExportPdfFactory implements ExportFactory {
@Override
public ExportFile factory(String type) {
// TODO Auto-generated method stub
if("standard".equals(type)){
return new ExportStandardPdfFile();
}else if("financial".equals(type)){
return new ExportFinancialPdfFile();
}else{
throw new RuntimeException("没有找到对象");
}
}
}

抽象导出角色类源代码:
public interface ExportFile {
public boolean export(String data);
}
具体导出角色类源代码,通常情况下这个类会有复杂的业务逻辑。

public class ExportFinancialHtmlFile implements ExportFile{
@Override
public boolean export(String data) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
System.out.println("导出财务版HTML文件");
return true;
}
}


public class ExportFinancialPdfFile implements ExportFile{
@Override
public boolean export(String data) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
System.out.println("导出财务版PDF文件");
return true;
}
}


public class ExportStandardHtmlFile implements ExportFile{
@Override
public boolean export(String data) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
System.out.println("导出标准HTML文件");
return true;
}
}


public class ExportStandardPdfFile implements ExportFile {
@Override
public boolean export(String data) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
System.out.println("导出标准PDF文件");
return true;
}
}

客户端角色类源代码:

public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String data = "";
ExportFactory exportFactory = new ExportHtmlFactory();
ExportFile ef = exportFactory.factory("financial");
ef.export(data);
}
}

工厂方法模式的活动序列图
客户端创建ExportHtmlFactory对象,这时客户端所持有变量的静态类型为ExportFactory,而实际类型为ExportHtmlFactory。然后客户端调用ExportHtmlFactory对象的工厂方法factory(),接着后者调用ExportFinancialHtmlFile的构造子创建出导出对象。
工厂方法模式和简单工厂模式
工厂方法模式和简单工厂模式在结构上的不同很明显。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
工厂方法模式退化后可以变得很像简单工厂模式。设想如果非常确定一个系统只需要一个具体工厂类,那么不妨把抽象工厂类合并到具体工厂类中去。由于只有一个具体工厂类,所以不妨将工厂方法改为静态方法,这时候就得到了简单工厂模式。
如果系统需要加入一个新的导出类型,那么所需要的就是向系统中加入一个这个导出类以及所对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的导出类型而言,这个系统完全支持“开-闭原则”。
完结
一个应用系统是由多人开发的,导出的功能是你实现的,但是使用者(调用这个方法的人)可能却是其他人。这时候你应该设计的足够灵活并尽可能降低两者之间的耦合度,当你修改或增加一个新的功能时,使用者不需要修改任何地方。假如你的设计不够灵活,那么将无法面对客户多变的需求。可能一个极小的需求变更,都会使你的代码结构发生改变,并导致其他使用你所提供的接口的人都要修改他们的代码。牵一处而动全身,这就使得日后这个系统将难以维护。
via:http://www.cnblogs.com/java-my-life/archive/2012/03/25/2416227.html
《JAVA与模式》之工厂方法模式的更多相关文章
- Java设计模式3:工厂方法模式
工厂方法模式 工厂方法模式是类的创建模式.工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工厂推迟到子类中. 工厂方法模式 工厂方法模式是对简单工厂模式进一步抽象的结果. 假如是不使用反 ...
- Java设计模式之【工厂模式】(简单工厂模式,工厂方法模式,抽象工厂模式)
Java设计模式之[工厂模式](简单工厂模式,工厂方法模式,抽象工厂模式) 工厂模式出现的原因 在java中,创建一个对象最简单的方法就是使用new关键字.但在一些复杂的业务逻辑中,创建一个对象不只需 ...
- Java设计模式学习记录-简单工厂模式、工厂方法模式
前言 之前介绍了设计模式的原则和分类等概述.今天开启设计模式的学习,首先要介绍的就是工厂模式,在介绍工厂模式前会先介绍一下简单工厂模式,这样由浅入深来介绍. 简单工厂模式 做法:创建一个工厂(方法或类 ...
- JAVA设计模式(01):创建型-工厂模式【工厂方法模式】(Factory Method)
简单工厂模式尽管简单,但存在一个非常严重的问题.当系统中须要引入新产品时,因为静态工厂方法通过所传入參数的不同来创建不同的产品,这必然要改动工厂类的源码,将违背"开闭原则".怎样实 ...
- 重学 Java 设计模式:实战工厂方法模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!
- 设计模式---对象创建模式之工厂方法模式(Factory Method)
前提:“对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式(表现最为突出) 工 ...
- PHP简单工厂模式、工厂方法模式和抽象工厂模式比较
PHP工厂模式概念:工厂模式是一种类,它具有为您创建对象的某些方法.您可以使用工厂类创建对象,而不直接使用 new.这样,如果您想要更改所创建的对象类型,只需更改该工厂即可.使用该工厂的所有代码会自动 ...
- PHP简单工厂模式、工厂方法模式和抽象工厂模式
PHP工厂模式概念:工厂模式是一种类,它具有为您创建对象的某些方法.您可以使用工厂类创建对象,而不直接使用 new.这样,如果您想要更改所创建的对象类型,只需更改该工厂即可.使用该工厂的所有代码会自动 ...
- iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下 ...
- iOS经常使用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
1. 简单工厂模式 怎样理解简单工厂,工厂方法. 抽象工厂三种设计模式? 简单工厂的生活场景.卖早点的小摊贩.他给你提供包子,馒头,地沟油烙的煎饼等,小贩是一个工厂.它生产包子,馒头,地沟油烙的煎饼. ...
随机推荐
- 【转载】解析 java 按值传递还是按引用传递
原文链接 说明: (1):“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递. (2):在Java里面只有基本类型和 ...
- FeignClient注解及参数
一.FeignClient注解 FeignClient注解被@Target(ElementType.TYPE)修饰,表示FeignClient注解的作用目标在接口上 1 2 3 4 5 @FeignC ...
- 杭电ACM2017--字符串统计
字符串统计 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- C# 实体类转json数据过滤掉字段为null的字段
C# 实体类转json数据过滤掉字段为null的字段 语法如下: var jsonSetting = new JsonSerializerSettings {NullValueHandling = N ...
- jQuery(六)、事件
1 页面载入 1.ready(fn) 当DOM载入完后绑定一个要执行的函数. 这是事件模块中最重要的一个函数,可以极大地提高web应用程序的响应速度. $(document).ready(functi ...
- weblogic 安全漏洞 CVE-2017-5638
关于安全漏洞 CVE-2017-5638 的 Weblogic Server 防护建议 关于Weblogic Server如何防护防止近期爆出的Struts 2远程代码执行安全漏洞,为您提供以下内容参 ...
- 小米平板8.0以上系统如何不用root激活xposed框架的流程
在大多使用室的引流,或业务操作中,基本上都需要使用安卓的强大XPOSED框架,近来我们使用室购来了一批新的小米平板8.0以上系统,基本上都都是基于7.0以上系统版本,基本上都不能够刷入ROOT的su权 ...
- Simulink 产品说明
Simulink 产品说明 仿真和基于模型的设计 Simulink® 是一个模块图环境,用于多域仿真以及基于模型的设计.它支持系统级设计.仿真.自动代码生成以及嵌入式系统的连续测试和验证.Simuli ...
- Linux(CentOS 7)安装测试mysql5.6服务
1.rpm -qa | grep mysql,查看原系统中是否有已经安装得mysql. 注:centos7系统在安装完成后,未安装mysql任何版本. 2. rpm -e --nodeps mysql ...
- C#事件与委托详解
from https://www.cnblogs.com/sjqq/p/6917497.html C#事件与委托详解[精华 多看看] Delegatedelegate是C#中的一种类型,它实际上是一个 ...
