《Effective java》 Java 随笔

前言

读完了Effective Java前几章,结合自己在实际中的使用,记录一些感觉比较有用的点

1.用静态工厂方法代替构造器

考虑采用静态工厂方法代替构造器

public class Pizza {
private String dough;
private String sauce;
private String topping;
private String cheese;

public Pizza(String dough, String sauce, String topping,String cheese) {
this.dough = dough;
this.sauce = sauce;
this.topping = topping;
this.cheese = cheese;
}

public static Pizza noCheesePizza(String dough, String sauce, String topping){
return new Pizza(dough,sauce,topping,null);
}

public static Pizza cheesePizza(String dough, String sauce, String topping,String cheese){
return new Pizza(dough,sauce,topping,cheese);
}
}

优点1:静态工厂方法的名字由自己命名,而构造方法必须与类名相同
假如我们想要提供多个具有相同签名的构造器,这在Java中是做不到的,除非把参数列表的顺序做些调整,但这会对用户很不友好。
因此可以使用静态工厂方法,取不同的名字以表示不同的构造方式。

适用于类中含有多个构造器的情况,可以通过准确命名的静态方法返回我们需要的对象

 

优点2:构造方法每次调用都会创建一个对象,而静态工厂方法则不会每次调用时都创建要给对象。
适用于单例模式。

优点3:静态工厂方法可以返回原返回类型的任何子类型对象,这样在我们选择返回对象的类时就有了更大的灵活性

运用到了多态

缺点:
a. 类如果不含有公有的类或者受保护的构造器,就不能被子类化

b. 它们与其他的静态方法实际上没什么区别,因此我们约定了一些静态工厂方法的常用名称

2.遇到多个构造器参数时考虑用建造者模式(Builder)

一般做法:

 例如有这个一个类的构造函数:

public Register(int id, int age, String name, String address, String like, int high, int weight)

 

那么此时的做法:

new Register(1, 20, "A", "B", "C", 170, 60);

 

这样的缺点就是:
1. 参数会很乱,调用者很容易搞错参数的位置
2. 如果不想为某个参数赋值,那么你还是要赋值,除非你另写一个没有该值的构造函数

Builder模式

public class Register {
private int id;
private int age;
private String name;
private String address;
private String like;
private int high;
private int weight;

public static class Builder {
private int id;
private String name;
private int age;
private String address;
private String like;
private int high;
private int weight;

public Builder(int id, String name) {
this.id = id;
this.name = name;
}

public Builder age(int age){
this.age = age;
return this;
}

public Builder address(String address){
this.address = address;
return this;
}

public Builder like(String like){
this.like = like;
return this;
}

public Builder high(int high){
this.high = high;
return this;
}

public Builder weight(int weight){
this.weight = weight;
return this;
}

public Register build(){
return new Register(this);
}
}

//私有化
private Register(Builder builder){
id = builder.id;
name = builder.name;
age = builder.age;
address = builder.address;
like = builder.like;
high = builder.high;
weight = builder.weight;
}
}
 

此时的用法:

Register re = new Register.Builder(1, "liu").age(20).address("LA").like("Ball").high(180);

3.当使用数组或集合时,返回零长度的数组或集合而不是null

可以避免程序员调用,未判断null,而报NullPointerException

4.优先使用组合

组 合 关 系 继 承 关 系
优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立 缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性
优点:具有较好的可扩展性 缺点:支持扩展,但是往往以增加系统结构的复杂度为代价
优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象 缺点:不支持动态继承。在运行时,子类无法选择不同的父类
优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口 缺点:不支持动态继承。在运行时,子类无法选择不同的父类
缺点:整体类不能自动获得和局部类同样的接口 优点:子类能自动继承父类的接口
缺点:创建整体类的对象时,需要创建所有局部类的对象 优点:创建子类的对象时,无须创建父类的对象

总结:

  1. 满足 is-a,才继承
  2. 如果父类的API有缺陷,继承是否担心吧这些缺陷传到子类中?
  3. 继承会打破封装性
  4. 优先使用组合

 




posted @ 2021-12-06 00:06  忧伤的丹丹  阅读(30)  评论(0)    收藏  举报