一天一个设计模式——工厂方法(FactoryMethod)模式
一、模式说明
在前一个模板方法(Template Method)模式中,父类定义了处理流程,而流程中用到的方法交给子类去实现。类似的,在工厂方法模式中,父类决定如何生成实例,但并不决定所要生成的具体类,具体的处理交由子类来处理。这样可以将生成实例的框架和实例本身解耦。
工厂方法模式在很多框架中都有用到,在面试中也问的比较多的,需要重点理解把握。
二、工厂方法(Factory Method)模式类图

三、工厂方法(Factory Method)模式中的角色
- Product产品类【框架】:定义了工厂方法模式生成的实例应该持有哪些接口。
- Creater创建者类【框架】:负责生成Product角色的抽象类。Creater角色对最终生成的实例是一无所知的,它只知道,只要调用Product角色和工厂方法(factoryMethod),就可以生成Product的实例,无需调用new方法,这样可以将父类和其他具体类耦合。
- ConreteProduct具体的产品类:工厂方法生成的具体产品。
- ConcreteCreater具体的创建者类:负责生成具体的产品。
四、工厂方法(Factory Method)代码示例:
1、模式框架类的创建,Product类:
package com.designpattern.cn.factorymethodpattern.patternframework;
public abstract class Product {
public abstract void use();
}
2、模式框架类的创建,Factory类:
package com.designpattern.cn.factorymethodpattern.patternframework;
public abstract class Factory {
public final Product create(String owner){
Product product = this.createProduct(owner);
this.registerProduct(product);
return product;
}
protected abstract Product createProduct (String owner);
protected abstract void registerProduct(Product product);
}
3、模式实现类,IDCard身份证类:
package com.designpattern.cn.factorymethodpattern.patterndemostrate;
import com.designpattern.cn.factorymethodpattern.patternframework.Product;
public class IDCard extends Product {
private String owner;
IDCard(String owner){
System.out.println("制作" + owner + "的ID卡");
this.owner = owner;
}
public void use(){
System.out.println("使用" + this.owner + "的ID卡");
}
public String getOwner() {
return owner;
}
}
4、模式实现类,IDCardFactory类:
package com.designpattern.cn.factorymethodpattern.patterndemostrate; import com.designpattern.cn.factorymethodpattern.patternframework.Factory;
import com.designpattern.cn.factorymethodpattern.patternframework.Product; import java.util.ArrayList;
import java.util.List; public class IDCardFactory extends Factory {
private List owners = new ArrayList();
protected Product createProduct(String owner){
return new IDCard(owner);
} protected void registerProduct(Product product){
owners.add(((IDCard)product).getOwner());
} public List getOwners(){
return owners;
}
}
5、Main方法类与运行结果:

上面的代码示例中,工厂模式的createProduct是一个抽象方法,必须在子类中实现该方法,具体可以选择三种实现方式:
- 指定其为抽象方法,如同上面的代码示例一样;
- 为其实现默认处理:
public Product createProduct(String name){
return new Product(name);
}
如果采用这种方式,Product类就不能定义为抽象类。
3.抛出异常的方式:
public Product createProduct(String name){
throw new FactoryMethodRuntimeException();
}
这样一来,就必须在子类中重写该方法,否则会抛出异常。
五、工厂方法(Factory Method)模式相关的模式
- 模板方法(Template Method)模式:工厂方法模式是模板方法模式的典型应用,工厂方法中的createProduct就是模板方法。
- 单例模式(Singleton):工厂方法模式中,具体的创建者角色(上例中的IDCardFactory)类,可以设计为单例模式,因为程序中没有必要存在多个创建者角色的实例(后续学习到单例模式时再回头修改这个示例)。
- 组合(Composite)模式:将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。工厂方法模式中的Creater和ConcreteCreater对象可以用到该模式。
- 迭代器(Iterator)模式:在迭代器模式中,使用iterator方法生成Iterator实例时,会使用工厂方法模式。
一天一个设计模式——工厂方法(FactoryMethod)模式的更多相关文章
- 设计模式之工厂方法(FactoryMethod)模式
在五大设计原则的基础上经过GOF(四人组)的总结,得出了23种经典设计模式,其中分为三大类:创建型(5种).结构型(7种).行为型(11种).今天对创建型中的工厂方法(FactoryMethod)模式 ...
- 工厂方法(FactoryMethod)模式
之前说了简单工厂设计模式如果增加一个新的运算的时候需要:增加一个具体的实现类,工厂类中增加一个case分支.也就是说我们不但对扩展开发了,也对修改开放了,违背了开闭原则.当然如果工厂类采用反射的话不存 ...
- 一天一个设计模式——模板方法(Template Method)模式
一.模式说明 现实世界中的模板是用于将事物的结构规律予以固定化.标准化的成果,它体现了结构形式的标准化.例如镂空文字印刷的模板,通过某个模板印刷出来的文字字体大小都是一模一样,但是具体使用什么材质的颜 ...
- 4. 星际争霸之php设计模式--工厂方法模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- C++设计模式——工厂方法模式
本文版权归果冻说所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.» 本文链接:http://www.jellythink.com/arch ...
- 工厂方法FactoryMethod 初步学习笔记
一,意图 定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 二,别名 虚构造器 Virtual Constructor 三,适用性 当一个类不知道它 ...
- 设计模式-工厂方法模式(FactoryMethod)
简介: 简单工厂模式将类的示例化放在工厂对象中. 工厂方法模式是简单工厂模式的延伸,不同的是其将子类的实例化延迟到子类工厂中实现,本身仅定义一个创建对象的接口. 工厂方法模式主要由四部分组成: 1.抽 ...
- Java设计模式---工厂方法模式(Factory-Method)
一.普通工厂模式 建立一个工厂类,对实现了同一接口的一些类进行实例的创建 实例代码: 发送短信和邮件的例子,首先创建接口: public interface Sender { public void ...
- Python设计模式——工厂方法模式(FactoryMethod)
需求:有一个学雷锋活动,有买米和扫地两个内容,参与的人有大学生和社区志愿者,他们各自的方法不一样. 如果用简单工厂模式实现: #encoding=utf-8 __author__ = 'kevinlu ...
随机推荐
- Linux 补丁 的简单使用: 制作补丁,打补丁,撤销补丁
背景: 补丁的使用对于嵌入式开发人员来说,在维护或者开发中都比较方便. 制作补丁: diff - 逐行比较文件. 格式: diff 参数 旧文件/旧文件夹 新文件/新文件夹 (注意顺序 新旧文件夹 ...
- 配置uboot指定nfs挂载根文件系统
背景: 文件系统的调试也建议在 网络中进行. 概念: NFS是Network File System的缩写及网络文件系统. 要功能是通过局域网络让不同的主机系统之间可以共享文件或目录. NFS系统和W ...
- KMP【模板】 && 洛谷 P3375
题目传送门 解题思路: 首先说KMP的作用:对于两个字符串A,B(A.size() > B.size()),求B是否是A的一个字串或B在A里的位置或A里有几个B,说白了就是字符串匹配. 下面创设 ...
- Java中遍历 Session 和 Request
转: session的遍历: java.util.Enumeration e = request.getSession().getAttributeNames(); while( e.hasMoreE ...
- 013.CI4框架CodeIgniter数据库操作之:查询数据库,并让数据以数组的方式返回查询结果
01. 我们在CI4框架中的Model文件夹新建一个User_model.php的文件,使用的是getResultArray,表示并让数据以数组的方式返回查询结果,代码如下: <?php nam ...
- 006、MySQL取当前系统时间
#取当前时间文本格式 SELECT curdate( ) , now( ); 效果如下图: 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:3824772 ...
- 7.1 Varnish VCL
根据以上的配置增加集群,修改default.vcl # This ) # man page for details on VCL syntax and semantics. # # Default b ...
- js封装ajax
//封装ajax function ajax(obj) { //创建xhr对象; var xhr = new XMLHttpRequest(); obj.method = obj.method.toU ...
- WC2020 联训 #19 矩阵
好不容易自己切一道题 链接 Description 在一个 \(n×(n+1)\) 的棋盘上放棋子, \(n\) 行中每行都恰好有两枚棋子,并且 \(n+1\) 列中每列都至多有两枚棋子,设 \(n= ...
- Linux基础之防火墙
Linux基础之防火墙 Iptables 最初认识iptables还是在安卓手机上玩tiny的时候知道的,什么扫地僧.Jume等防跳脚本都基于iptables原理,一直觉得iptables的命令很 ...