Effective第三版 中英 | 第二章 创建和销毁对象 | 固定资源首选使用依赖注入

news2024/11/25 4:22:34

文章目录

  • Effective第三版
    • 前言
    • 第二章 创建和销毁对象
      • 固定资源首选使用依赖注入

Effective第三版

前言

大家好,这里是 Rocky 编程日记 ,喜欢后端架构及中间件源码,目前正在阅读 effective-java 书籍。同时也把自己学习该书时的笔记,代码分享出来,供大家学习交流,如若笔记中有不对的地方,那一定是当时我的理解还不够,希望你能及时提出。如果对于该笔记存在很多疑惑,欢迎和我交流讨论,最后也感谢您的阅读,点赞,关注,收藏~

前人述备矣,我只是知识的搬运工,effective 书籍源码均在开源项目 java-diary 中的 code-effective-third 模块中

源代码仓库地址: https://gitee.com/Rocky-BCRJ/java-diary.git

第二章 创建和销毁对象

固定资源首选使用依赖注入

在这里插入图片描述

  Many classes depend on one or more underlying resources. For example, a spell checker depends on a dictionary. It is not uncommon to see such classes implemented as static utility classes(Item 4):

  许多类依赖于一个或多个底层资源。例如,拼写检查器依赖于字典。常见的做法是将这些类实现为静态实用程序类(第 4 项):

// Inappropriate use of static utility - inflexible & untestable!
public class SpellChecker {
    private static final Lexicon dictionary = ...;
    private SpellChecker() {} // Noninstantiable
    public static boolean isValid(String word) { ... }
    public static List<String> suggestions(String typo) { ... }
}

  Similarly, it’s not uncommon to see them implemented as singletons (Item 3):

  同样的,将它们作为单例实现的情况并不少见(第 3 项):

// Inappropriate use of singleton - inflexible & untestable!
public class SpellChecker {
    private final Lexicon dictionary = ...;
    private SpellChecker(...) {}
    public static INSTANCE = new SpellChecker(...);
    public boolean isValid(String word) { ... }
    public List<String> suggestions(String typo) { ... }
}

  Neither of these approaches is satisfactory, because they assume that there is only one dictionary worth using. In practice, each language has its own dictionary, and special dictionaries are used for special vocabularies. Also, it may be desirable to use a special dictionary for testing. It is wishful thinking to assume that a single dictionary will suffice for all time.

  这些方法都不令人满意,因为它们假设只有一本值得使用的字典。在实践中,每种语言都有自己的字典,特殊字典用于特殊词汇。而且,可能需要使用特殊字典进行测试。假设单本字典就足以满足所有情况,这是一厢情愿的想法。

  You could try to have SpellChecker support multiple dictionaries by making the dictionary field nonfinal and adding a method to change the dictionary in an existing spell checker, but this would be awkward, error-prone, and unworkable in a concurrent setting. Static utility classes and singletons are inappropriate for classes whose behavior is parameterized by an underlying resource.

  你可以尝试让 SpellChecker 支持多个词典,方法是使字典字段为非 final 域,并添加一个方法来更改现有拼写检查器中的字典,但这在并发时设置会很笨拙,容易出错并且不可行。静态实用程序类和单例不适用于将底层资源作为参数的类(Static utility classes and singletons are inappropriate for classes whose behavior is parameterized by an underlying resource.)。

  What is required is the ability to support multiple instances of the class (in our example, SpellChecker), each of which uses the resource desired by the client (in our example, the dictionary). A simple pattern that satisfies this requirement is to pass the resource into the constructor when creating a new instance. This is one form of dependency injection: the dictionary is a dependency of the spell checker and is injected into the spell checker when it is created.

  所需要的是能够支持类的多个实例(在我们的示例中为 SpellChecker),每个实例都使用客户端所需的资源(在我们的示例中为字典)。满足此要求的简单模式是在创建新实例时将资源传递给构造函数。这是依赖注入的一种形式:字典是拼写检查器的依赖项,并在创建时注入拼写检查器。

// Dependency injection provides flexibility and testability
public class SpellChecker {
    private final Lexicon dictionary;
    public SpellChecker(Lexicon dictionary) {
        this.dictionary = Objects.requireNonNull(dictionary);
    }
    public boolean isValid(String word) { ... }
    public List<String> suggestions(String typo) { ... }
}

  The dependency injection pattern is so simple that many programmers use it for years without knowing it has a name. While our spell checker example had only a single resource (the dictionary), dependency injection works with an arbitrary number of resources and arbitrary dependency graphs. It preserves immutability (Item 17), so multiple clients can share dependent objects (assuming the clients desire the same underlying resources). Dependency injection is equally applicable to constructors, static factories (Item 1), and builders (Item 2).

  这种依赖注入很简单,以至于程序猿用了很多年却不知道它有一个名称。虽然我们的拼写检查器只有一个资源(字典),但是依赖注入可以使用任意数量的资源和任意的依赖关系,它保留了不变性(第 17 项),因此多个客户端可以共享依赖对象(假设客户端需要相同的底层资源)。依赖注入同样适用于构造函数、静态工厂(第 1 项)和构建器(第 2 项)。

  A useful variant of the pattern is to pass a resource factory _to the constructor. A factory is an object that can be called repeatedly to create instances of a type. Such factories embody the _Factory Method pattern [Gamma95]. The Supplier interface, introduced in Java 8, is perfect for representing factories. Methods that take a Supplier on input should typically constrain the factory’s type parameter using a bounded wildcard type (Item 31) to allow the client to pass in a factory that creates any subtype of a specified type. For example, here is a method that makes a mosaic using a client-provided factory to produce each tile:

  将资源工厂传递给构造函数就会变成一个有用的模式。工厂是一个对象,通过重复调用这个工厂可以创建某个类型的实例对象。这些就是工厂方法模式 [Gamma95]。Java 8 中引入的 Supplier<T>;接口非常适合体现工厂。在输入上采用 Supplier<T>的方法通常应该使用泛型(第 31 项)约束工厂的类型参数,以允许客户端传入创建指定类型的任何子类型的工厂。例如,这是一种使用客户提供的工厂生成马赛克来生成每个图块的方法:

Mosaic create(Supplier<? extends Tile> tileFactory) { ... }

  Although dependency injection greatly improves flexibility and testability, it can clutter up large projects, which typically contain thousands of dependencies. This clutter can be all but eliminated by using a dependency injection framework, such as Dagger [Dagger], Guice [Guice], or Spring [Spring]. The use of these frameworks is beyond the scope of this book, but note that APIs designed for manual dependency injection are trivially adapted for use by these frameworks.

  尽管依赖注入极大地提高了灵活性和可测试性,但它可能会使大型项目更加混乱,这些项目通常包含数千个依赖项。通过使用依赖注入框架,例如 Dagger [Dagger],Guice [Guice]或 Spring [Spring],可以消除这种混乱。这些框架的使用超出了本书的范围,但请注意,为手动依赖注入而设计的 API 可以轻松地适用于这些框架。

  In summary, do not use a singleton or static utility class to implement a class that depends on one or more underlying resources whose behavior affects that of the class, and do not have the class create these resources directly. Instead, pass the resources, or factories to create them, into the constructor (or static factory or builder). This practice, known as dependency injection, will greatly enhance the flexibility, reusability, and testability of a class.

  总之,如果有一个类依赖一个或多个底层资源的类,并且底层资源类影响了类的行为,不要使用单例或静态实用程序类来实现它,并且不要让类直接创建这些资源(do not use a singleton or static utility class to implement a class that depends on one or more underlying resources whose behavior affects that of the class)。相反,将资源或工厂传递给构造函数(或静态工厂或构建器)。这种做法称为依赖注入,将极大地增强类的灵活性,可重用性和可测试性。

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

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

相关文章

接招吧!MySQL 10 连问

文章目录 &#x1f349;1. 索引底层采用什么数据结构&#xff1f;为什么不用hash&#x1f349;2. B树与B树区别&#xff1f;为何用B树&#xff1f;&#x1f349;3. 自增主键理解&#xff1f;&#x1f349;4. 为什么自增主键不连续&#x1f349;5. Innodb为什么推荐用自增ID&…

Jetpack Compose 中的基础组件

Button 默认样式 Button的lambda块中可以传入任意的Composable组件&#xff0c;但一般是放一个Text在里面 Button(onClick { println("确认onClick") }) {Text("默认样式") }按钮的宽高 如果想要宽一点或高一点的Button&#xff0c;可以通过Modifier修…

chatgpt赋能python:Python平面图制作教程

Python平面图制作教程 Python是一种高级编程语言&#xff0c;也是数据科学和机器学习领域中使用最广泛的编程语言之一。在数据可视化中&#xff0c;Python语言具有优秀的表现力和灵活性&#xff0c;可以为用户展示各种数据可视化方案。这篇文章将重点介绍Python如何制作平面图…

八字诀 · 十年之约

* * * 原创&#xff1a;刘教链 * * * 号外&#xff1a;今天在“刘教链Pro”发表了两篇文章&#xff0c;《一视同仁&#xff0c;SEC起诉Coinbase》和《SEC起诉币安的官方新闻稿》&#xff0c;欢迎关注“刘教链Pro”并阅读。 * * * 隔夜比特币奋力反弹&#xff0c;重新回升至27k…

激发数学思维:GPT-4实证研究探索挑战性数学问题

深度学习自然语言处理 原创作者&#xff1a;wkk 考虑到自然语言在许多科学和工程领域表达的数学问题的丰富性&#xff0c;使用大语言模型(LLM)来解决数学问题是一项有趣的研究工作。今天给大家介绍一篇微软研究院联合欧美高校关于如何使用GPT-4解决数学问题的研究论文。 之前的…

KCC@深圳 邀你共享『升压手电DIY』的创新之旅!

嘿&#xff0c;亲爱的KCC深圳的社区成员们&#xff01;你们是否曾经梦想过拥有一款强大的手电&#xff0c;能够在黑暗中照亮一切&#xff1f;现在&#xff0c;我将揭开一个让你们眼前一亮的活动——『升压手电DIY』&#xff01; 在这个充满创意的活动中&#xff0c;我们将带你们…

为什么我们是RISC-V的首选 GPU

谈起 GPU&#xff0c;很容易想到 Imagination。毫无疑问&#xff0c;鉴于 Imagination 在图形处理领域的积累&#xff0c;也成为 RISC-V 的首选 GPU。 凭借 30 多年的 PowerVR GPU&#xff0c;Imagination 非常熟悉图形处理器。在过去的时间里&#xff0c;我们不断创新&#xf…

总结893

学习目标&#xff1a; 月目标&#xff1a;6月&#xff08;线性代数强化9讲&#xff0c;背诵15篇短文&#xff0c;考研核心词过三遍&#xff09; 周目标&#xff1a;线性代数强化3讲&#xff0c;英语背3篇文章并回诵&#xff0c;检测 每日必复习&#xff08;5分钟&#xff09;…

java数组and二维数组

文章目录 java一维数组1.数组定义和定义格式1.1 定义1.2格式 2.数组初始化2.1数组动态初始化2.1.1格式 2.2动态数组初始化取值2.2.1格式 2.3 静态数组初始化取值2.3.1格式 3.数组求长度4.数组遍历 java二维数组1.二维数组动态初始化2.二维数组遍历3.二维数组长度 数组赋值1整数…

聊一聊Netflix 技术栈-数据库

大家好&#xff01;今天我们来聊一聊全球最受欢迎的视频流媒体平台Netflix的技术栈。作为一个庞大的流媒体服务提供商&#xff0c;Netflix需要强大的数据库支持来实现规模化的视频播放。让我们一起来看看Netflix选择了哪些数据库来支撑他们的业务。 在Netflix的技术栈中&#x…

define与const什么使用区别

&#x1f6a9;define &#x1f38c;一.define的使用方法 &#x1f380;1.定义常量 #define M 10010 int main() {cout << M << endl;cout << M M << endl;//cout << M << end;//会报错return 0; }我们定义了一个名为M的常数&#xff0…

Effective第三版 中英 | 第二章 创建和销毁对象 | 避免创建不需要的对象

文章目录 Effective第三版前言第二章 创建和销毁对象避免创建不需要的对象 Effective第三版 前言 大家好&#xff0c;这里是 Rocky 编程日记 &#xff0c;喜欢后端架构及中间件源码&#xff0c;目前正在阅读 effective-java 书籍。   同时也把自己学习该书时的笔记&#xff…

我爸嘲讽我,写破代码一年才挣十几万,他在工地带50个工人,一个月仅人头费就挣3万多,让我滚回去跟他干工地!...

现在码农的地位有多低&#xff1f; 一位程序员讲述自己被父亲鄙视的经过&#xff1a; 我爸嘲讽我&#xff0c;说我天天写这破代码有啥用&#xff0c;一年就拿十多万死工资。他在工地带 50 个工人&#xff0c;一个人一天抽 20 块钱人头费&#xff0c;一个月都能抽 3 万多&#x…

MTK 相机内存知识点

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点 一、Camera 内存包含哪些内容二、VSS/RSS/PSS/USS 内存介绍三、内存查看常用命令四、内存泄漏相关知识点五、参考文献 一、Camera 内存包含哪些内容 1.1…

DeepFaceLive AI实时换脸软件安装流程

第一&#xff1a;设置虚拟内存≥32G 在安装DeepFaceLive前&#xff0c;需把电脑的虚拟内存设置≥32G。鼠标移到左下角WIN处&#xff0c;右击后选择【系统】模块。 在显示的【系统信息】页面选择【高级系统设置】。 在显示的【系统属性】页面中&#xff0c;选择【高级】选项&…

【MySQL数据库 | 第四篇】SQL通用语法及分类

目录 &#x1f914;SQL通用语法&#xff1a; &#x1f60a;语句&#xff1a; &#x1f60a;注释&#xff1a; &#x1f914;SQL语句分类&#xff1a; &#x1f60a;1.DDL语句&#xff1a; &#x1f60a;2.DML语句&#xff1a; &#x1f60a;3.DQL语言&#xff1a; &…

不写代码也能年薪百万?Prompt+低代码开发实战

&#x1f449;腾小云导读 近期 AIGC 狂潮席卷&#xff0c;“前端走向穷途”“低代码时代终结”的言论甚嚣尘上。事实上 GPT 不仅不会干掉低代码&#xff0c;反而会大幅度促进低代码相关系统的开发。本文会介绍 GPT Prompt Engineering 的基本原理&#xff0c;以及如何帮助低代码…

elementui大型表单校验

一般很大的表单都会被拆解开&#xff0c;校验&#xff0c;&#xff0c;不会写在一个页面&#xff0c;&#xff0c;就会有多个 el-form &#xff0c;&#xff0c;主页要集合所有el-form的数据&#xff0c;&#xff0c;所以有一个map来接收&#xff0c;传送表单数据&#xff0c;&…

【Android】脱壳之frida-dexdump小计

前言 最近在挖客户端漏洞时&#xff0c;遇到了加壳的情况&#xff0c;之前没解决过&#xff0c;遇到了就解决一下。特此记录。 本文详细介绍了frida-dexdump脱壳原理相关知识并且在实战中进行了脱壳操作。 基本知识 1. Frida-dexdump frida-dexdump通过以下步骤实现DEX文件…

qemu+buildroot+linux arm64虚拟化-宿主系统wsl2

文章目录 1.qemu2.buildroot配置编译 3.linux kernel下载交叉编译工具链 linux kernel 5.16配置内核config_kernel.shbuild_kernel.sh 4.启动虚拟机start_qemu.sh参数解释运行 环境&#xff1a; wls2、qemu8.2、buildroot、linuxkernel 1.qemu https://buildroot.org/download…