为什么说静态工厂方法可能会比构造器更好?听说读完就会有一个女朋友?

2024-06-15 07:32

本文主要是介绍为什么说静态工厂方法可能会比构造器更好?听说读完就会有一个女朋友?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 什么是静态工厂方法
    • 静态工厂方法比构造器好在哪里
      • 静态工厂方法有名称而构造器没有(前者可读性更好)
      • 不必每次调用它们的时候都创建一个新对象
      • 可以返回原返回类型的任何子类对象
      • 创建泛型对象可以更加简洁
    • 静态工厂的局限之处
    • 总结

前言:相信读过《Effective Java》(第二版)的小伙伴知道我在说什么,作者在书中总结了78条黄金建议,其中建议的第一条就是:考虑用静态工厂方法替代构造器。可以说是开幕雷击,第一条我就懵X了,什么是静态工厂方法?为什么要替代构造器?是构造器不香吗?本文将根据这些疑问刨根问底,详细分析静态工厂方法的优劣,相信我,有问题欢迎评论指出,本篇文章一定不会枯燥,坚持读完哦~

在这里插入图片描述

什么是静态工厂方法

当我们想要获得一个类的实例对象的时候,恐怕一下子就通过new一个对象来获得了。那么静态工厂方法是怎么实现的呢?其实也很简单:

public static Girl newGirlFriend(boolean isBeautifulGirl) {return new Girl(isBeautifulGirl);
}

如此,我们通过类名加newGirlFriend就可以轻松地拿到对象。

所谓的静态工厂方法就是不通过new,而通过一个静态方法返回自身的实例对象

静态工厂方法比构造器好在哪里

由《Effective Java》可以得到四点静态工厂方法比构造器好的地方:
①静态工厂方法有名称而构造器没有(前者可读性更好)
②不必每次调用它们的时候都创建一个新对象
③可以返回原返回类型的任何子类对象(不局限于单一特定的类)
④创建泛型对象可以更加简洁

静态工厂方法有名称而构造器没有(前者可读性更好)

说到有名称这点,构造器是真的没法儿比:

public class GirlFriend {private boolean isBeautiful;private boolean isTall;public GirlFriend(){}public GirlFriend(boolean isBeautiful) {this.isBeautiful = isBeautiful;    }public GirlFriend(boolean isBeautiful, boolean isTall) {this.isBeautiful = isBeautiful;    this.isTall = isTall;    }
}

调用者如果不是非常熟悉这段代码,必须要看文档中有哪些重载的构造方法,稍有不慎,就会调错,毕竟构造方法都是一个名字,只有参数不同而已。但是静态工厂方法就不一样了,可以起很多能让调用者见名知意的名字:getBeautifulGirlfriend(); getTallGirl();,是不是看出差距了

另外:正是因为这一特性,所以哪怕他们有相同的参数,也不会报错,如果构造器有两个构造方法含有相同参数,必定出错,但是任性的静态工厂方法想怎么起名字就怎么起名字,完美避过了这个坑~
在这里插入图片描述

不必每次调用它们的时候都创建一个新对象

当我们需要获得类的实例对象的时候,为了性能,我们不在乎他是不是新对象,使用new必然会得到一个不同地址的对象(姑且称之为新对象),当我们使用new GirlFriend();这种方式直接创建对象,相当于对JVM说,我要一个对象,然后JVM会去根据双亲委派原则加载验证准备解析(new一个对象发生了什么?),所以开支是蛮大的,尤其在重复新建一个对象的时候。小斌哥我之前的代码就都是这种毛病,并没有使用单例模式,每个方法都new同一个对象,我去,简直是伤害了我的CPU,心疼我的旧电脑,怪不得那么快就挂了(玩笑话);使用静态工厂方法最简单的一个例子就是单例模式,我们可以确保获取多个对象的时候只需要创建一次对象并且销毁一次对象,这样就很“环保”了,对内存的开支会达到最小,这点是构造器望尘莫及的。

说到单例模式,大家会想到“饿汉式”与“懒汉式”,举个最简单的例子不考虑线程安全给大家展示一下单例模式是如何做到多次获取对象只创建并销毁一次:
饿汉式:

public class Singleton{private static Singleton singleton = new Singleton ();private Singleton (){}public static Singleton getInstance(){return singleton;
}

懒汉式:

public class Singleton{private static Singleton singleton = null;public static Singleton getInstance(){if(singleton==null){singleton = new Singleton();}return singleton;}
}

使用单例模式不管创建多少次都会返回相同的对象,所以相当于对象被多次循环利用了,提升了效率。在这里插入图片描述

可以返回原返回类型的任何子类对象

这体现了里氏原则:任何基类可以出现的地方,子类一定可以出现。 比如有这样的UML:
在这里插入图片描述

public static Singleton getGirlFriend(){return new 女朋友();//可以返回新垣结衣()、长泽雅美()、松冈茉优()、绫濑遥()//因为都是女朋友的子类
}

这个优点有些欺负构造器了,毕竟它没有返回值。

创建泛型对象可以更加简洁

作者想表示过去泛型书写比较复杂,比如:

Map<String, List<String>> map = new HashMap<String, List<String>>(); 

额,但是jdk1.7之后这个问题已经木有了,毕竟这本书有一定年头了(第二版参考的是jdk1.6),所以就当这条没有吧。

另外,静态工厂方法还有其他好处,比如可以隐藏实现细节,只提供用户最简单的方法入口,比如让你写一个计算器软件,用户只需要输入:3*(7/1.455)+11-12,而方法的具体实现细节是私有的,用户是看不到的,也不需要看到,否则就体现不了封装的特性了,一个是用户使用着麻烦,另外是出错的可能性更大,你暴露给用户更多的参数更多的方法,出BUG的可能性就更大。这就好比现在的手机,只有关机键、音量键,如果把手机后盖拆开暴露给你,手机被整坏的可能性必然会提升啊。。

我们熟知的工具类Collections就是一个很好的例子,他把构造器设置为私有,所以调用者不能通过new来调用类中的方法,只能通过类名加方法名去调用,并且内部需要计算的方法都设为private,调用者看不到也不需要去知道,比如sort方法和binarySearch等。

静态工厂的局限之处

凡事都是两面的,虽然静态工厂方法很好,但是它只要构造方法私有化了,就不能被实例化,也就是说,想让拒绝访问构造器的类拥有子类是不可能的(就像做了绝育手术)。第二点就是它跟普通的静态方法没啥两样,虽然我们管它叫静态工厂方法,但是它依然只是一个很简单的静态方法而已,并不像构造器,有自己的专属名称,还可以在API文档中看到他的名字。但是静态工厂方法也会有一些不成文的规定,正如我们会看到一些newInstance()、valueOf()、getInstance()等,这些往往就是静态工厂方法实现的。

总结

作者给我们这条建议,并非让我们用静态构造方法彻底替换构造器,只是希望我们在以后可以有多一种选择,直接new并不是唯一的方法,他们各有各的好,需要我们去进行合适的选择。

这篇关于为什么说静态工厂方法可能会比构造器更好?听说读完就会有一个女朋友?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1062813

相关文章

豆包 MarsCode 不允许你还没有女朋友

在这个喧嚣的世界里,爱意需要被温柔地唤醒。为心爱的她制作每日一句小工具,就像是一场永不落幕的浪漫仪式,每天都在她的心田播撒爱的种子,让她的每一天都充满甜蜜与期待。 背景 在这个瞬息万变的时代,我们都在寻找那些能让我们慢下来,感受生活美好的瞬间。为了让这份浪漫持久而深刻,我们决定为女朋友定制一个每日一句小工具。这个工具会在她意想不到的时刻,为她呈现一句充满爱意的话语,让她的每一天都充满惊喜和感动

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

Thymeleaf:生成静态文件及异常处理java.lang.NoClassDefFoundError: ognl/PropertyAccessor

我们需要引入包: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>sp