Effective Java —— 优先考虑依赖注入来引用资源
本文参考
本篇文章参考自《Effective Java》第三版第五条"Prefer dependency injection to hardwiring resources"
Static utility classes and singletons are inappropriate for classes whose behavior is parameterized by an underlying resource
静态工具类模式和单例模式都不适合应用到需要将底层资源作为自身字段进行参数化的类,这个引用的资源可以是一个接口,他对应有很多的实现,不同的实现应对不同的场景
静态工具类模式往往不需要进行实例化,而且有一个无参的private构造方法来强化noninstantiability的特性,他需要引用的资源在类加载时就已经被构建,尽管我们可以再设计一个静态方法来修改引用的资源,但并不是灵活和方便测试的方式
虽然单例模式存在一个实例,但是这个实例仅允许被初始化一次,所以引用的资源也只能被参数化一次,难以按照不同场景下的需求进行改变
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.
pass the resource into the constructor when creating a new instance
要解决上述问题,便要求能够用不同的资源构建不同的实例,我们可以通过构造方法来实现不同资源的参数化,这就是依赖注入的其中一种解决方案(同样可以应用到前述的静态工厂方法和构建者模式),这与Spring中的"构造注入"类似,它也能够保证不同的客户端共享同一份引用的资源,即"preserves immutability"
pass the resources, or factories to create them( refer to the fields using underlying resources ), 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.
a variant of the pattern is to pass a resource factory to the constructor
原文提供了一种使用Supplier<T>接口的Factory Method Pattern(工厂方法模式)
有关Supplier的使用,参考这篇文章:https://mkyong.com/java8/java-8-supplier-examples/
以马赛克为例,工厂方法模式的示例代码如下,顺便复习一下builder构建者模式
public class Tile {
private String name;
private int price;
private String origin;
public static class Builder {
private String name;
private int price;
private String origin;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder price(int price) {
this.price = price;
return this;
}
public Builder origin(String origin) {
this.origin = origin;
return this;
}
public Tile build() {
return new Tile(this);
}
}
private Tile(Builder builder) {
name = builder.name;
price = builder.price;
origin = builder.origin;
}
public String getName() { return name; }
public int getPrice() { return price; }
public String getOrigin() { return origin; }
}
public class Mosaic {
private Tile tile;
private String style;
private Mosaic(String style) {
this.style = style;
}
public static Mosaic create(Supplier<? extends Tile> tileFactory) {
Tile tile = tileFactory.get();
if (tile.getOrigin().equals("American")) {
return new Mosaic("USA-STYLE");
} else {
return new Mosaic("GENERAL_STYLE");
}
}
public Tile getTile() { return tile; }
public String getStyle() { return style; }
}
public class SupplierExample {
public static void main(String[] args) {
Mosaic product = Mosaic.create(() -> new Tile.Builder().origin("American").build());
System.out.println(product.getStyle());
}
}
Effective Java —— 优先考虑依赖注入来引用资源的更多相关文章
- 在ABAP里模拟实现Java Spring的依赖注入
Dependency Injection- 依赖注入,在Java Spring框架中有着广泛地应用.通过依赖注入,我们不必在应用代码里繁琐地初始化依赖的资源,非常方便. 那么ABAP能否从语言层面上也 ...
- Java Spring各种依赖注入注解的区别
Spring对于Bean的依赖注入,支持多种注解方式: @Resource javax.annotation JSR250 (Common Annotations for Java) @Inject ...
- JavaEE(10) - Session EJB的依赖注入、引用及任务调度
1. EJB依赖注入 #1. EJB开发(Net Beans创建EJB Module, 项目名称:CallHello) Hello.java package org.crazyit.service; ...
- JAVA框架 Spring 依赖注入
一:介绍 情景:我们在给程序分层的时候:web层.业务层.持久层,各个层之间会有依赖.比如说:业务层和持久层,业务层的代码在调用持久层的时候,传统方式:new 持久层类. 进而进行调用,这种方式会导致 ...
- 详解Java Spring各种依赖注入注解的区别
注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.Service.Controller.Repository.Comp ...
- 【Java】 Spring依赖注入小试牛刀:编写第一个Spring ApplicationContext Demo
0 Spring的依赖注入大致是这样工作的: 将对象如何构造(ID是什么?是什么类型?给属性设置什么值?给构造函数传入什么值?)写入外部XML文件里.在调用者需要调用某个类时,不自行构造该类的对象, ...
- Effective Java 第三版——43.方法引用优于lambda表达式
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Java代码实现依赖注入
http://zhangjunhd.blog.51cto.com/113473/126545 这里将模仿Spring实现一种基于xml配置文件的依赖注入机制.文件中将实现3中注入,一是单值注入,包括i ...
- Java反射及依赖注入简单模拟
一.编写Dao类 ? 1 2 3 4 5 6 7 8 9 10 11 package cn.com.songjy.annotation; import java.util.Date; publ ...
随机推荐
- Nullable<T> 结构 |T? 可为空的值类型
参考链接:https://www.cnblogs.com/tdfblog/p/Nullable-Types-in-Csharp-Net.html https://www.cnblogs.com/min ...
- Linux概述及简单命令
Linux概述及简单命令 转自https://www.cnblogs.com/ayu305/p/Linux_basic.html 一.准备工作 1.环境选择:VMware\阿里云服务器 2.Linux ...
- 2016EC Final F.Mr. Panda and Fantastic Beasts
题目大意 \(T(1\leq T\leq42)\)组数据,给定\(n(2\leq n\leq 50000)\)个字符串\(S_{i}(n\leq\sum_{i=1}^{n}S_{i}\leq 2500 ...
- Qt:打印输出到控制台,类似C++的cout
1. #include<qDebug> 2. qDebug<<"Hello,world!"; 补充,如果不是控制台文件,比如是窗口应用程序,需要在pro文件 ...
- 无法cin一个string 没有找到接受“std::string”类型的右操作数的运算符(或没有可接受的转换)
头文件#include<string>不能写成#include<string.h>
- LeetCode-055-跳跃游戏
跳跃游戏 题目描述:给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 . 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个下标. 示例说明请见LeetCod ...
- Azure DevOps (三) 实现和Jenkins的联动
上一篇文章中,我们通过azure 的webhook实现了和钉钉机器人的联动,实现了通过钉钉机器人告知大家刚才谁动了仓库. 在文章开篇的时候我们举例说了jenkins也可以实现和azure联动,今天我们 ...
- SpringBoot连接Redis (Sentinel模式&Cluster模式)
一.引入pom <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- think php 验证码
1.下载 composer require topthink/think-captcha 1.* // composer 下载 //过程 D:\PHP\phpstudy_pro\WWW\1906A\p ...
- 拉格朗日插值法--python
数据插补 常见插补方法 插值法--拉格朗日插值法 根据数学知识可知,对于平面上已知的n个点(无两点在一条直线上可以找到n-1次多项式 ,使次多项式曲线过这n个点. 1)求已知过n个点的n-1次多项式: ...