Java设计模式:Factory Method(工厂方法)模式
概念定义
工厂方法(Factory Method)模式,又称多态工厂(Polymorphic Factory)模式或虚拟构造器(Virtual Constructor)模式。工厂方法模式通过定义工厂抽象父类(或接口)负责定义创建对象的公共接口,而工厂子类(或实现类)则负责生成具体的对象。
工厂方法模式对简单工厂模式中的工厂类进一步抽象。核心工厂类不再负责产品的创建,而是演变为一个抽象工厂角色,仅负责定义具体工厂子类必须实现的接口。同时,针对不同的产品提供不同的工厂。即每个产品都有一个与之对应的工厂。这样,系统在增加新产品时就不会修改工厂类逻辑而是添加新的工厂子类,从而弥补简单工厂模式对修改开放的缺陷。
在实际项目中,工厂方法模式是使用较多的工厂模式。
应用场景
- 当一个类不知道它所需要的对象的类时
在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建。 - 当一个类希望通过其子类来指定创建哪个对象时
在工厂方法模式中,抽象工厂类只需提供一个创建产品的接口,而由其子类来确定具体要创建的对象。利用面向对象的多态性和里氏替换原则,程序运行时子类对象将覆盖父类对象,从而使得系统更容易扩展。 - 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心是哪个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
示例代码
工厂方法模式由工厂接口(或抽象类)、一组实现工厂接口工厂类、一个产品接口(或抽象类)和一组实现产品接口的具体产品组成。某具体产品由其对应的具体工厂类创建。
本节通过一个"喜闻乐见"的豪车系列,展示简单工厂模式的实现。示例代码如下:
// 产品接口 //
public interface ICar { // 也可定义为抽象类,但接口扩展性更好
void drive();
}
// 若干具体的产品 //
public class Bmw implements ICar {
@Override
public void drive() { System.out.println("drive a Bmw"); }
}
public class Benz implements ICar {
@Override
public void drive() { System.out.println("drive a Benz"); }
}
public class Audi implements ICar {
@Override
public void drive() { System.out.println("drive a Audi"); }
}
// 工厂接口 //
public interface IFactory { // 也可定义为抽象类,但接口扩展性更好
public ICar create();
}
// 若干具体的工厂,与具体产品一一对应 //
public class BmwFactory implements IFactory {
@Override
public ICar create() { return new Bmw(); }
}
public class BenzFactory implements IFactory {
@Override
public ICar create() { return new Benz(); }
}
public class AudiFactory implements IFactory {
@Override
public ICar create() { return new Audi(); }
}
客户端通过new BenzFactory().create().drive()即可创建Benz实例并调用其drive()方法。新增豪车时,只需要新增豪车自身产品类和对应的工厂类,而不需要修改任何已有类。
开源框架中,常常通过配置文件制定具体的工厂类,其模式形如:
public <T> T getProduct(typeOrName) {
IProductFactory iProductFactory = getIProductFactory(); // 通过配置文件获取具体工厂类
return iProductFactory.getProduct(typeOrName);
}
模式优缺点
工厂方法模式的优点如下:
- 客户端只依赖产品的抽象,符合依赖倒置原则;无需关注具体产品,符合迪米特(最少知识)原则。
- 工厂方法模式符合开放封闭原则,新增产品时只需增加相应的产品和工厂类,而无需修改现有代码。
- 工厂方法模式符合单一职责原则,每个具体的工厂类只负责创建对应的产品。
- 工厂方法模式不使用静态工厂方法,可以形成基于继承的等级结构。
缺点如下:
- 新增产品时除增加新产品类外,还要增加对应的具体工厂类,没有简单工厂代码简洁、高效。
- 为了扩展性而进一步引入抽象层,增加了系统的抽象性和理解难度。
业界实践
- org.slf4j.LoggerFactory.getLogger(slf4j-api-1.7.25.jar)
- org.springframework.context.support.AbstractApplicationContext.getBean(spring-context-4.3.4.RELEASE.jar)
Java设计模式:Factory Method(工厂方法)模式的更多相关文章
- Factory Method 工厂方法模式
Factory method工厂方法模式是一种实现了“工厂”概念的面向对象设计模式.就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题.工厂方法模式的实质是“定义一个创建对象 ...
- 《JAVA设计模式》之工厂方法模式 (Factory)
在阎宏博士的<JAVA与模式>一书中开头是这样描述工厂方法模式的: 工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymor ...
- 设计模式C++学习笔记之五(Factory Method工厂方法模式)
工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的 ...
- java设计模式-----2、工厂方法模式
再看工厂方法模式之前先看看简单工厂模式 工厂方法模式(FACTORY METHOD)同样属于一种常用的对象创建型设计模式,又称为多态工厂模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变的 ...
- Java设计模式3:工厂方法模式
工厂方法模式 工厂方法模式是类的创建模式.工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工厂推迟到子类中. 工厂方法模式 工厂方法模式是对简单工厂模式进一步抽象的结果. 假如是不使用反 ...
- 重学 Java 设计模式:实战工厂方法模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!
- 四、Factory Method 工厂方法模式
需求:对象的创建由工厂统一创建,会使用到模板模式 代码清单: 工厂: public abstract class Factory { public abstract Product createPro ...
- 面向对象设计模式纵横谈:Factory Method 工厂方法模式(笔记记录)
从耦合关系谈起 耦合关系直接决定着软件面对变化时的行为 -模块与模块之间的紧耦合使得软件面对变化时,相关模块都要随之更改 -模块与模块之间的松耦合使得软件面对变化时,一些模块更容易被替换或者更改,但其 ...
- C#面向对象设计模式纵横谈——5.Factory Method 工厂方法模式(创建型模式)
动机 (Motivation) 在软件系统中,经常面临着“某个对象”的创建工作; 由于需求的变化,这个对象经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何应对这种变化?如何提供一种“封装机制” ...
随机推荐
- Linux系统学习 十、DHCP服务器—介绍和原理
介绍: DHCP服务作用(动态主机配置协议) 为大量客户机自动分配地址.提供几种管理 减轻管理和维护成本.提高网络配置效率 可分配的地址信息主要包括: 网卡的IP地址.子网掩码 对应的网路地址.广播地 ...
- 因果推理的春天系列序 - 数据挖掘中的Confounding, Collidar, Mediation Bias
序章嘛咱多唠两句.花了大半个月才反反复复,断断续续读完了图灵奖得主Judea Pearl的The Book of WHY,感觉先读第四章的案例会更容易理解前三章相对抽象的内容.工作中对于归因问题迫切的 ...
- Python网络爬虫_Scrapy框架_1.新建项目
在Pycharm中新建一个基于Scrapy框架的爬虫项目(Scrapy库已经导入) 在终端中输入: ''itcast.cn''是为爬虫限定爬取范围 创建完成后的目录 将生成的itcast.py文件移动 ...
- JavaScript-----13.内置对象 Math()和Date()
1. 内置对象 js对象分为3种:自定义对象(var obj={}).内置对象.浏览器对象. 前两种对象是js基础内容,属于ECMAScript,第三个浏览器对象是js独有的.讲js API的时候会讲 ...
- 网易发起“疾风”智造IoT联盟,深化“互联网+先进制造业”发展
7月26日,2019网易云创峰会在杭州拉开序幕,本次峰会以“连接•洞察•进化”为主题,汇聚行业领袖.技术大咖及业界代表,探讨技术演进与行业应用趋势,研商生态合作升级.共赢未来的道路.上午的主论坛中,网 ...
- jvaa之初始化块
1.初始化块的作用:对java对象进行初始化: 2.程序的执行顺序:声明成员变量的默认值-->显示初始化,多个初始化块依次被执行(同级别下按先后顺序执行)-->构造器在对成员进行赋值操作. ...
- 呵呵,asp.net 屁东西我都会忘记
ASP.NET中的好些基本的东西有的忘了,有的需要学,从现在开始,给自己开一个基本的常用知识点的总结,一是学习,二是备忘. 今天算是第一篇吧! DropDownList在从数据库中得到数据源绑定后,计 ...
- Django之web框架原理
Web框架原理 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 先写一个 原始的web框架 imp ...
- WebShell代码分析溯源(三)
WebShell代码分析溯源(三) 一.一句话变形马样本 <?php $g = array('','s');$gg = a.$g[1].ser.chr('116');@$gg($_POST[ge ...
- Winform中设置ZedGraph鼠标悬浮显示举例最近曲线上的点的坐标值和X轴与Y轴的标题
场景 Winform中设置ZedGraph鼠标双击获取距离最近曲线上的点的坐标值: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/ ...