失效链接处理 |
Effective Java读书笔记 PDF 下载
本站整理下载:
提取码:o9oo
相关截图:
主要内容:
第一条:用静态工厂方法代替构造器
优点:
1.静态工厂方法有名称,更易被使用。
2.不必在每次调用他们的时候都创建一个新对象。
3.他们可以返回原返回类型的任何子类型的对象。
4.所返回对象的类可以随着每次调用而发生变化,这取决于静态工厂方法的参数值。
5.方法返回的对象所属的类,在编写包含该静态方法的类时可以不存在。
{(注:服务提供者框架:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来)
(注:服务提供者框架的重要组件:
服务接口:提供者实现的。
提供者注册API:提供者用来注册实现的。
服务访问API:客户端用来获取服务的实例。
服务提供者接口:他表示产生服务接口之实例的工厂对象。)
举例:JDBC
服务接口:connection
提供者注册API:DriverManager.registerDriver
服务访问接口:DriverManager.getConnection
服务提供者:Driver
服务访问API可以返回比提供者需要的更丰富的服务接口。(桥接模式)
}
缺点:
1.类如果不含公有的或者受保护的构造器,就不能被子类化
2.程序员很难发现他们。
静态工厂一些惯用名称:
From: Date b = Date.from(instant);
Of: Set<Rank> faceCards = EnumSet.of(JACK,QUEEN,KING);
valueOf: BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
instance或getInstance: getStackWalker luke = StackWalker.getInstance(options);
create或newInstance: Object newArray = Array.newInstance(classObject,arrayLen);
getType: Filestore fs = Files.getFileStore(path);
newType: BufferedReader br = Files.newBufferedReader(path);
type: List<complaint>litany = Collections.list(legacyLitany);
第二条:遇到多个构造器参数时要考虑使用构建器
重叠构造器模式:在这种模式下,提供的第一个构造器只有必要的参数,第二个构造器有一个可选参数,第三个构造器有两个可选参数,依此类推,最后一个构造器包含所有的可选参数。这种模式可行,但是当许多参数的时候,客户端代码会很难编写,并且仍然难以阅读。
JavaBeans模式:调用一个无参构造器创建对象,利用setter方法设置每个必要的参数,以及每个相关的可选参数。这种模式弥补了重叠构造器的不足,且易读性很高,但是其自身存在着很严重的缺点:当出现高并发的情况下,在构造过程中可能处于不一致的状态(类似于数据库中幻读的状态),而另一点在于JavaBeans模式使得把类做成不可变的可能性不复存在,而这对于程序员在保证其线程安全的操作上需要付出格外的努力。(可能出现两个线程同时读取一个数的情况。)
建造器模式(Builder模式):他不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象,然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法来生成通常是不可变的对象。这个builder通常是他构建的类的静态成员类。
(我认为可以这么想,Builder类创建了一个具有必要元素的builder对象,而这个对象并非不可变,而Builder类中,还包含了添加参数的方法,而这些方法的返回值则是已经添加好这些参数的builder对象,由此,通过不断的调用,我们便可以创造出一个具有我们想要的具有任何参数的一个builder对象,之后,我们再通过build方法,创建出一个私有的、基本上不可变的对象)
Builder模式的可读性的体现:模拟了具名的可选参数
另外,Builder模式也适用于类层次的结构。(我的理解是说,builder类可以被继承)
协变返回类型:子类方法声明返回超级类中声明的返回类型的子类型,它允许客户端无需转换类型就能使用这些构建器。
如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是一种不错的选择。使用Builder模式的客户端代码将更易于阅读和编写,构建器也比JavaBeans更加安全。
实例:NutritionFacts.java
package first;
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder{
private final int servingSize;
private final int servings;
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
NutritionFactsTest.java
package first;
public class NutritionFactsTest {
public static void main(String args[]) {
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();
System.out.println(cocaCola);
}
}
|