写出优美的代码:考虑使用静态工厂方法替代构造方法

news2024/11/29 2:47:31

文章目录

  • 一、静态工厂方法区别于工厂方法模式
  • 二、静态工厂方法的优点
    • 1、有名字
      • (1)优势
      • (2)源码分析:BigInteger
      • (3)源码分析:Executors
      • (4)常用命名 名称
    • 2、不需要每次调用时都创建一个新对象
      • (1)优势
      • (2)源码分析:Boolean
    • 3、可以返回原返回类型的任何子类型
      • (1)优势
      • (2)源码分析:Collections
    • 4、返回对象的类可以根据输入参数的不同而不同
      • (1)优势
      • (2)源码分析:EnumSet
    • 5、编写包含该方法的类时,返回的对象的类不需要存在
  • 三、总结

一、静态工厂方法区别于工厂方法模式

本文的静态工厂方法与设计模式的工厂方法模式完全不同,要注意区分!

通常来说,我们创建一个类对象,直接使用new 调用其构造方法进行创建。但是静态工厂方法提供一个公共静态工厂方法,它是一个返回类实例的静态方法。

比如,获取一个People实例:

public static People getInstance() {
	return new People();
}

而不是通过调用构造方法获取People实例(此处只是举个静态工厂方法的例子,实际上有诸多用法)。

二、静态工厂方法的优点

1、有名字

(1)优势

区别于构造方法,静态工厂方法是有名字的,正因为它是一个方法,它可以给方法取任意的方法名。

有的类中构造方法有很多,如果不仔细描述构造方法中的参数含义,其创建的对象很难理解它们有什么不同的含义。
在一个类中需要具有相同签名的多个构造方法的情况下,用静态工厂方法替换构造方法,并仔细选择名称来突出它们的差异,创建对象时很容易就知道其方法的含义了。

(2)源码分析:BigInteger

BigInteger有众多的构造方法,单看这些构造方法,并不能很清晰的知道其具体的含义,需要翻遍注释慢慢去了解。

而使用静态工厂方法,可以根据其语义,很轻松知道该方法会返回一个什么对象。
在这里插入图片描述
例如BigInteger(int, int, Random)返回一个素数,但调用者很难理解API设计者所要想表达的意思,如果此时有BigInteger.probablePrime静态工厂方法,则能一目了然的清楚API设计者所要想表达的含义。

(3)源码分析:Executors

Java线程池ThreadPoolExecutor类共有七大参数,如果仅仅使用构造方法来创建线程池,恐怕对于一个新人程序员来说这是一个噩梦。

Executors类定义了newFixedThreadPool、newFixedThreadPool等等诸多静态工厂方法,使用寥寥几个参数就可以获取一个特定功能的线程池,因为它们有“名字”,并且做了一些封装与默认值,所有就较为清晰的明白API的含义。
在这里插入图片描述

(4)常用命名 名称

  • from——A 类型转换方法,它接受单个参数并返回此类型的相应实例,例如:Date d = Date.from(instant);
  • of——一个聚合方法,接受多个参数并返回该类型的实例,并把他们合并在一起,例如:Set faceCards = EnumSet.of(JACK, QUEEN, KING);
  • valueOf——from 和 to 更为详细的替代 方式,例如:BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
  • instance 或 getinstance——返回一个由其参数 (如果有的话) 描述的实例,但不能说它具有相同的值,例如:StackWalker luke = StackWalker.getInstance(options);
  • create 或 newInstance——与 instance 或 getInstance 类似,除了该方法保证每个调用返回一个新的实例,例如:Object newArray = Array.newInstance(classObject, arrayLen);
  • getType——与 getInstance 类似,但是如果在工厂方法中不同的类中使用。Type 是工厂方法返回的对象类型,例如:FileStore fs = Files.getFileStore(path);
  • newType——与 newInstance 类似,但是如果在工厂方法中不同的类中使用。Type 是工厂方法返回的对象类型,例如:Buw eredReader br = Files.newBuw eredReader(path);
  • type—— getType 和 newType 简洁的替代方式,例如:List litany = Collections.list(legacyLitany);
  • 其他——根据方法的具体逻辑,简单描述方法的功能

2、不需要每次调用时都创建一个新对象

(1)优势

使用构造方法每次都会在内存中创建一个新对象,而静态工厂方法可以允许对象提前缓存或重用。

如果经常请求等价对象,或者某些对象创建时需要消耗极大的代价,它可以极大地提高性能。

这种技术常用于Flyweight(享元) 模式或者Singleton (单例)模式
设计模式之【享元模式】,共享单车火起来并不是没有原因的
设计模式之【单例模式】全解,单例模式实现方式,暴力打破单例模式与解决方案,你真的认识单例模式吗?

比如说一个最简单的饿汉式单例:

public class Instance() {
	private static Instance instance = new Instance();
	private Instance(){}
	public static Instance getInstance() {
		return instance;
	}
}

注意!静态工厂方法返回相同的对象,需要在任何时候保持对该对象实例的严格控制,这样做的类也叫实例控制( instance-controlled)。这也很好理解,因为如果该对象使用享元模式进行共享,修改了对象的属性及内容,所有引用该对象的地方都会感知到这一事件。

(2)源码分析:Boolean

Boolean的valueOf方法就是基于这种思想,提前将True和False进行缓存,每次获取的都是相同的实例,这避免了每次通过构造方法创建新的对象,极大的提高了性能。

同时,其构造方法,在jdk9就已经弃用了。

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

@IntrinsicCandidate
public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

@Deprecated(since="9", forRemoval = true)
public Boolean(boolean value) {
    this.value = value;
}

3、可以返回原返回类型的任何子类型

(1)优势

这种方式在选择返回对象的类时提供了很大的灵活性。这种技术适用于基于接口的框架,其中接口为静态工厂方法提供自然返回类型。

比如说Collections工具类,List list = Collections.synchronizedList(new ArrayList()) ,这与装饰者模式非常像:
设计模式之【装饰者模式】,实现“穿衣打扮”自由原来这么简单

(2)源码分析:Collections

Collections工具类中提供了大量的包装类。
在这里插入图片描述
比如说,synchronizedList,将传入的参数进行包装,将所有的方法都加上synchronized确保线程安全,这相当于装饰者模式的一种落地实现:
在这里插入图片描述
在这里插入图片描述

4、返回对象的类可以根据输入参数的不同而不同

(1)优势

这个优点与上一个优点类似,返回的类动态变化,一定是需要继承与本类或者实现了与本类相同的接口。

(2)源码分析:EnumSet

EnumSet的noneOf它们根据底层枚举类型的大小返回两个子类中的一个的实例:如果大多数枚举类型具有 64 个或更少的元素,静态工厂将返回一个RegularEnumSet 实例, 返回一个 long 类型;如果枚举类型具有六十五个或更多元素,则工厂将返回一个JumboEnumSet 实例,返回一个 long 类型的数组。

这两个实现类的存在对于客户是不可见的。 如果 RegularEnumSet 不再为小枚举类型提供性能优势,则可以在未来版本中将其淘汰,而不会产生任何不良影响。 同样,未来的版本可能会添加 EnumSet 的第三个或第四个实现,如果它证明有利于性能。 客户既不知道也不关心他们从工厂返回的对象的类别; 他们只关心它是 EnumSet 的一些子类。
在这里插入图片描述

5、编写包含该方法的类时,返回的对象的类不需要存在

这种灵活的静态工厂方法构成了服务提供者框架的基础,比如 Java 数据库连接 API(JDBC)。服务提供者框架是提供者实现服务的系统,并且系统使得实现对客户端可用,从而将客户端从实现中分离出来。

例如DriverManager.getConnection,获取的连接mysql、oracle是根据Driver驱动进行动态连接的。JDK只提供了DriverManager进行jdbc管理,而客户端需要各大厂商自行实现,实现了客户端与服务提供者进行分离。

同理,slf4j日志门面也是如此,门面和具体的实现分离,各自进行维护。

这也类似于门面模式的一种落地。

三、总结

虽然静态工厂方法有诸多优点,但是要结合实际应用场景。

如果只有静态工厂方法而没有公共或受保护构造方法,这将导致该类无法提供子类。例如,在 Collections框架中不可能将任何方便实现类子类化。可以说,这可能是因祸得福,因为它鼓励程序员使用组合而不是继承,并且是不可变类型(final)。

另外,静态工厂方法在API文档上,和普通静态方法混杂在一起,因此要想区分静态工厂方法和普通静态方法,或许要花费一定的精力。所以,静态工厂方法的命名很有讲究(参考本文静态工厂方法的命名)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1166271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue 自动登录示例

router.beforeEach((to, from, next) > {if (to.meta.title) {document.title "xxxxx" to.meta.title;}let token window.sessionStorage.getItem(userInfo);// 如果没有token 并且没有任何响应 就要去action中自动登录if (!token) {const loginForm {usernam…

在紫光同创盘古50K开发板上进行DDR读写测试

本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处 适用于板卡型号: 紫光同创PGL50H开发平台(盘古50K开发板) 一:软硬件平台 软件平台:PDS_…

DI93a HESG440355R3 通过其Achilles级认证提供网络安全

DI93a HESG440355R3 通过其Achilles级认证提供网络安全 施耐德电气宣布推出Modicon M580以太网PAC (ePAC)自动化控制器,该控制器采用开放式以太网标准,通过其Achilles级认证提供网络安全。M580 ePAC使工厂操作员能够设计、实施和运行一个积极利用开放网…

vue:js中合并对象的方法

目前比较常用的一共有三种 1、使用object.assign() 它可以将一个或多个对象的属性复制到目标对象中&#xff0c;第一个参数就是目标对象&#xff0c;这里举个例子&#xff1a; <template><div>{{data}}</div> </template> <script> export de…

【t5 pytorch版源码学习】t5-pegasus-pytorch源码学习

0. 项目来源 中文生成式预训练模型&#xff0c;以mT5为基础架构和初始权重&#xff0c;通过类似PEGASUS的方式进行预训练。 bert4keras版&#xff1a;t5-pegasus pytorch版&#xff1a;t5-pegasus-pytorch 本次主要学习pytorch版的代码解读。 项目结构&#xff1a; train…

一站式IT统一运维管理平台有哪些?大家都在用哪个?

随着公司业务的加大&#xff0c;不少企业从最初的一个运维系统增加到了几个运维系统&#xff0c;每个都是独立存在的&#xff0c;因此给运维小伙伴带来了不少困扰。因此不少小伙伴在问&#xff0c;有没有一站式IT统一运维管理平台&#xff1f;有哪些&#xff1f;大家都在用哪个…

HMDD 4.0:miRNA-疾病关系数据库

拥有多项自主专利技 术和软件著作权&#xff0c;具 有丰富的数据库平台 搭建经验。 凌恩-盈飞团队 MicroRNA&#xff08;miRNA&#xff09;是一类重要的小非编码RNA&#xff0c;在疾病诊断和治疗中发挥着重要作用。人类 MicroRNA 疾病数据库 (HMDD) 为 miRNA 相关医学提供了…

zookeeper节点类型

节点类型 持久节点&#xff08;Persistent Nodes&#xff09; 这些是Zookeeper中最常见的一种节点类型&#xff0c;当创建一个持久类型节点时&#xff0c;该值会一直存在zookeeper中&#xff0c;直到被显式删除或被新值覆盖。 临时节点&#xff08;Ephemeral Nodes&#xff…

基于Qt 的可视化图片处理程序——图片的加载与保存

基于Qt 的可视化图片处理程序——图片的加载与保存 Chapter1 基于Qt 的可视化图片处理程序——图片的加载与保存图片的加载图片加载到 Label完整代码图片的保存保存图片完整代码 void MainWindow::loadPixmap() {QImage img,image;QPixmap pixmap;LoadPicPath QFileDialog::ge…

(免费领源码)java#ssm#mysql爱心捐赠物资维护系统09536-计算机毕业设计项目选题推荐

摘要 随着信息技术的快速发展&#xff0c;计算机应用已经进入成千上万的家庭。随着物资数量的增加&#xff0c;物资库存管理也存在许多问题。物资数据的处理量正在迅速增加&#xff0c;原来的手工管理模式不适合这种形式。使用计算机可以完成数据收集、处理和分析&#xff0c;减…

vue3框架全局修改样式(字体颜色以及初始化定义基础elemplent颜色)

问题1、全局修改vue管理系统框架的字体颜色&#xff08;index.scss目录下修改&#xff09; 问题2、vue3中使用elemplent-plus中的el-select组件&#xff0c;默认选中二级或三级的一个数据&#xff0c;没有显示label只显示了id 问题如下 原因是因为 这个属性为true了&#xff0…

springboot+mybatis查询两次数据库结果不一致

最近遇到个bug记录一下。情景再现&#xff1a;在一个方法里有多次查询数据库的操作&#xff0c;但查询出的数据字段会被自动翻译。&#xff08;比如1翻译成是&#xff0c;2翻译成否&#xff09;。原因&#xff1a;mybatis缓存会被代码修改。在同一个sqlsession下&#xff0c;第…

彩色颜料背景的团建活动策划PPT模板

这是一套彩色颜料背景的团建活动策划PPT模板&#xff0c;共24页&#xff1b; PPT模板封面&#xff0c;使用了彩色颜料墨迹背景图片。中间放置带有阴影效果的白色矩形文本框&#xff0c;填写团建活动策划PPT标题。界面风格充满青春朝气。 PowerPoint模板内容页&#xff0c;由2…

Rust语言和curl库编写程序

这是一个使用Rust语言和curl库编写的爬虫程序&#xff0c;用于爬取视频。 use std::env; use std::net::TcpStream; use std::io::{BufReader, BufWriter}; ​ fn main() {// 获取命令行参数let args: Vec<String> env::args().collect();let proxy_host args[1].clon…

JVM 内存和 GC 算法

文章目录 内存布局直接内存执行引擎解释器JIT 即时编译器JIT 分类AOT 静态提前编译器&#xff08;Ahead Of Time Compiler&#xff09; GC什么是垃圾为什么要GC垃圾回收行为Java GC 主要关注的区域对象的 finalization 机制GC 相关算法引用计数算法&#xff08;Reference Count…

【嵌入式开发学习】__软件工程师的关键原则-18个系统设计概念

目录 前言 01. 域名系统 (DNS) 02. 负载均衡器 03. API 网关 04. 内容交付网络 (CDN) 05. 正向代理与反向代理 06. 缓存 07. 数据分区 08. 数据库复制 09. 分布式消息系统 10. 微服务 11. 数据库 12. 前端缓存 13. 后端缓存 14. 安全性 15. 高可用性与容错性 …

阿里云双11优惠活动:新老用户99元服务器和代金券领取攻略

2023阿里云双11优惠活动开启了&#xff0c;轻量2核2G3M带宽服务器87元一年、2核4G4M带宽165元一年&#xff0c;云服务器ECS经济型e实例2核2G3M固定带宽优惠价格99元一年&#xff0c;新老用户同享&#xff0c;并且续费不涨价&#xff0c;第二年99元续费。阿里云个人和企业用户还…

JAVA技术栈的有福啦!这款IDEA插件,写完代码即可调试

国产API调试工具 Apipost 推出IDEA插件&#xff0c;写完代码就可以调试接口并一键生成接口文档&#xff01;而且还可以根据已有的方法帮助您快速生成 url 和 params。Apipost Helper API 调试工具 API 管理工具 API 搜索工具。 在商店中搜索或直接点击下方链接即可下载&…

天猫商品评论API接口(评论内容|日期|买家昵称|追评内容|评论图片|评论视频..)

要获取天猫商品评论接口&#xff0c;您需要使用天猫开放平台提供的API接口。以下是一些可能有用的步骤&#xff1a; 注册并登录天猫开放平台&#xff0c;获取开发者账号。在开发者中心创建一个应用&#xff0c;获取应用的App Key和App Secret。使用天猫开放平台的API接口&…

Yolov8目标识别与实例分割——算法原理详细解析

前言 YOLO是一种基于图像全局信息进行预测并且它是一种端到端的目标检测系统&#xff0c;最初的YOLO模型由Joseph Redmon和Ali Farhadi于2015年提出&#xff0c;并随后进行了多次改进和迭代&#xff0c;产生了一系列不同版本的YOLO模型&#xff0c;如YOLOv2、YOLOv3、YOLOv4&a…