一文带你看懂工厂模式
大家好我是mihotel,今天来总结一下设计模式中的工厂模式,在平时编程中,构建对象最常用的方式是 new 一个对象。乍一看这种做法没什么不好,而实际上这也属于一种硬编码。每 new 一个对象,相当于客户端多知道了一个类,增加了类与类之间的联系,不利于程序的松耦合。我们可以利用工厂模式封装对象的生产过程。
简单工厂模式
首先是简单工厂模式,它是通过指定一个工厂对象来创建产品实例,只需要传给工厂参数,不需要关系对象是怎样产生的.
举个例子:如果我们要录制Java和Python两门课程,我们可以先创建ICourse接口, 提供录制功能:
public interface ICourse {void record();// 录制
}
然后分别创建JavaCourse类与PythonCourse类
public class JavaCourse implements ICourse {@Overridepublic void record() {System.out.println("录制Java课程");}
}public class PythonCourse implements ICourse {@Overridepublic void record() {System.out.println("录制Python课程");}
}
如果我们不使用工厂模式来创建对象,客户端的代码是这样的:
@Test
public void testFactory01() {ICourse java = new JavaCourse();java.record();ICourse python = new PythonCourse();python.record();
}
可以看到客户端直接依赖了JavaCourse对象和PythonCourse对象,随着业务发展耦合度会很高。
下面我们通过简单工厂模式解耦,创建简单工厂模式类:
public class SympleFactory {public <T> T getCourse(Class<T> clazz) {try {return clazz.newInstance();} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();}return null;}
}
利用简单工厂模式我们再来看看客户端实现,代码如下:
@Test
public void testFactory02() {SympleFactory sympleFactory = new SympleFactory();JavaCourse java = sympleFactory.getCourse(JavaCourse.class);java.record();PythonCourse python = sympleFactory.getCourse(PythonCourse.class);python.record();
}
可以看到现在客户端只与sympleFactory产生依赖,因此达到了解耦的作用。还需注意到,在SympleFactory中我们使用了反射来创建对象,避免了过多的 if else 语句。
总结一下:
简单工厂模式:
概念:指定一个工厂对象来创建产品实例,只需要传给工厂参数,不需要关系对象是怎样产生的.
好处:如果业务扩展客户端会依赖 “一坨”对象,耦合度高,通过简单工厂模式改造后只依赖工厂类,耦合度降低
缺点:不符合开闭原则,如果增加新的参数则需要修改创建对象的代码
工厂方法模式
可以看到简单工厂模式只适合生产少量的对象,如果生产的对象总类过多,既不符合单一职责原则,也会导致工厂类十分臃肿。工厂方法模式就解决了该问题,通过指定一个创建对象的接口,让实现这个接口的类来决定实例化哪一个类,实例化推迟到子类中进行。
举个例子,要开设多门编程语言课程比如java、python,下面我们用工厂方法模式来生产这些对象,首先定义一个ICourseFactory接口:
public interface ICourseFactory {ICourse create();
}
创建java工厂和python工厂:
public class JavaCourseFactory implements ICourseFactory{@Overridepublic ICourse create() {return new JavaCourse();}
}public class PythonFactory implements ICourseFactory {@Overridepublic ICourse create() {return new PythonCourse();}
}
再来创建客户端测试类:
@Test
public void testFactory03() {ICourseFactory javaCourseFactory = new JavaCourseFactory();ICourse java = javaCourseFactory.create();java.record();ICourseFactory pythonFactory = new PythonFactory();ICourse python = pythonFactory.create();python.record();
}
可以发现工厂方法模式符合单一职责原则,一个工厂的具体实现类只生产一种产品,并且符合开闭原则,当需要生产新的产品时不需要修改代码,只需要新增一个实现类即可。
总结一下:
工厂方法模式:
- 概念:指定一个创建对象的接口,让实现这个接口的类来决定实例化哪一个类,实例化推迟到子类中进行。
- 好处:用户只需要关心生产产品对应的工厂,不需要关系生产产品的细节,符合开闭原则
- 适用场景:
- 创建对象需要大量重复代码
- 客户端(应用层)不依赖产品实例如何被创建、如何被实现等细节
- 一个类通过其子类来指定创建哪个对象
抽象工厂模式
可以看到工厂方法模式生产是某个产品的专属工厂,而实际情况下我们往往需要生产一个产品类簇,比如空调和空调遥控器就属于一个产品类簇。下面还是举个例子,我们如果要开设编程课程,每门课程不止会有视频,还会有笔记,java课程有对应的视频和笔记,同理python课程也有。下面我们使用抽象工厂模式来生产“视频”和“笔记"这一个类簇的对象。首先创建视频接口和笔记接口:
public interface IVideo {void record();// 录制
}
public interface INote {void edit();// 编辑
}
然后创建对应的实现类:
public class JavaNote implements INote{@Overridepublic void edit() {System.out.println("java课程笔记");}
}
public class JavaVideo implements IVideo{@Overridepublic void record() {System.out.println("录制Java视频");}
}
然后我们创建CourseFactory接口作为顶层设计,用来生产”视频“和”笔记“这个产品类簇
public interface CourseFactory {INote createNote();IVideo createVideo();
}
接下来就是它的实现类:
public class JavaCourseFactory implements CourseFactory{@Overridepublic INote createNote() {return new JavaNote();}@Overridepublic IVideo createVideo() {return new JavaVideo();}
}
我们来看一下客户端调用:
public void testFactory04() {CourseFactory javaCourseFactory = new JavaCourseFactory();IVideo javaVideo = javaCourseFactory.createVideo();javaVideo.record();INote javaNote = javaCourseFactory.createNote();javaNote.edit();
}
客户端耦合了JavaCourseFactory,生产了属于一个产品类簇的对象。
总结一下
概念:指定一个接口生产创建一系列产品,或相互依赖的对象。
缺点:
类的个数容易过多
增加了系统抽象性和理解难度
不符合开闭原则,增加产品时从抽象工厂开始都要进行修改
增加了系统的抽象性和理解难度
到这里工厂模式就讲完了,希望能够帮助到大家。
参考
Spring 5 核心原理
深入浅出设计模式
大家好我是mihotel,此次的推文对设计模式中的工厂模式的学习总结,分析了为什么要使用工厂模式以及各工厂模式的优缺点,相信通过对工厂模式的学习利用,大家可以写出更加优雅的代码~大家也可关注公众号【学习休憩站】,不定期分享学习资源。
一文带你看懂工厂模式相关推荐
- java byte char io流_一文带你看懂JAVA IO流,史上最全面的IO教学
原标题:一文带你看懂JAVA IO流,史上最全面的IO教学 一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符 ...
- java io流详解_一文带你看懂JAVA IO流,史上最全面的IO教学啦
一.IO流是什么 惯例引用百科的回答流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操作 ...
- javaio流_一文带你看懂JAVA IO流,史上最全面的IO教学啦
一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操 ...
- 一文带你看懂JAVA IO流(一),史上最全面的IO教学啦(附送JAVA IO脑图)
一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操 ...
- 一文带你看懂JAVA IO流,史上最全面的IO教学啦(附送JAVA IO脑图
一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操 ...
- 机器学习(1)一文带你看懂显卡,显卡驱动,CUDA,CUDNN(内含举例)
一文带你看懂显卡,显卡驱动,CUDA,CUDNN(内含举例) 显卡 显卡驱动 CUDA CUDNN 举一个生动形象的例子 显卡 显卡是硬件设备.(花钱购买的) (注:显卡不是GPU,显卡的核心组件包含 ...
- 一文带你看懂 MySQL 存储引擎
本文目录: 1.MySQL体系结构 2.存储引擎介绍 3.MySQL 存储引擎特性 4.MySQL 有哪些存储引擎 5.了解 MySQL 数据存储方式 6.MySQL存储引擎介绍 6.1 CSV存储引 ...
- 一文带你看懂java 泛型,史上最全面的泛型教学啦。
认真看这篇文章,保证你们对泛型又有新的理解,如果没有的话,请顺着网线来打我呀. 概述 引用下百度百科的回答 泛型是程序设计语言的一种特性.允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那 ...
- 一文带你搞懂工厂设计模式
更多知识,请移步我的小破站:http://hellofriend.top 什么是工厂设计模式? 对象都需要创建,如果创建的时候直接 new 该对象,就会对该对象严重耦合. 假如我们要更换对象,所有 n ...
最新文章
- SDN要防止七种认识偏差
- 使用群集保障SQL Server 2005的高可用性(2)
- LeetCode 8 字符串转整数 (atoi)
- RedHat7.0更新yum源(踩过的坑)
- 【转】TCP/IP协议到底在讲什么?【乐搏TestPro】
- android action bar 风格,自定义ActionBar风格和样式
- 【Shell脚本】TDS离线备份还原
- oracle get_ddl XSL error 解决方法
- for里面嵌套if_求求你们了,别再写满屏的 if/ else 了!
- java多线程上传文件_Java大文件分片上传/多线程上传
- 认识CPU的工作原理
- Linux防火墙配置工具iptables中MASQUERADE的含义
- python stack unstack_Python之数据重塑
- 2021-09-10体脂模块做体脂秤方案,体脂秤模块原理解析
- win 7硬盘安装centos7 亲测可行
- 信贷风控报表常用指标解读(一)
- knockout js之select
- EasyUI API
- 牛客 刺客信条 (bfs、dijkstra)+堆优化、dfs三种求解
- 计算机视觉——bbox的格式简介
热门文章
- 分部积分出现积回去的情况
- c/c++算法之“24点”经典问题
- 海克斯康三坐标模块化c语言编程,海克斯康三坐标编程手册_海克斯康三坐标教程...
- 如何盘活新零售5大线上线下交互模式?拥抱用户与收益增长
- 电信卡 LTE 无法短信发送
- OSI和TCP/IP网络参考模型傻傻分不清?图解和各层作用详细说明
- 从零搭建一个自动化运维体系
- Web前端-JavaScript
- nextcloud19.0.1部署
- 电子邮件发送服务器怎么看钱,验证电子邮件的验证码是发到哪里