1、遇到多参构造器时要考虑使用构建器
一般情况下,我们在碰到多参构造器的时候,往往会使用重叠构造器。这种构造器虽然可以满足需求,、但是会使我们的代码看起来很臃肿,同时,可能由于参数位置的问题,但是构造器里面并无法进行校验,导致代码出错。总而言之,重叠构造器模式是可行的,但是当有很多参数的时候,客户端代码会很难编写,并且仍然难以阅读。
建造着模式:
public class Person {
//名字 必填
private final String name;
//身份证 必填
private final String IDCard;
//年龄
private final int age;
//职业
private final String job;
//爱好
private final String habbit;
public static class Builder{
private final String name;
private final String IDCard;
//可选
//年龄
private int age=0;
//职业
private String job ="";
//爱好
private String habbit ="";
public Builder(String name, String IDCard) {
this.name = name;
this.IDCard = IDCard;
}
public Builder age(int val){
age = val;
return this;
}
public Builder job(String val){
job = val;
return this;
}
public Builder habbit(String val)
{
habbit=val;
return this;
}
public Person build() {
return new Person(this);
}
}
public Person(Builder builder) {
name = builder.name;
age = builder.age;
IDCard = builder.IDCard;
habbit =builder.habbit;
job = builder.job;
}
}
如上所示,person类使用了构建器,这样开发者可以很方便的根据自己的选择去进行构建,同时代码更加的简洁。
Builder模式同样适用于类层次结构
package com.example.demo.effective_java.page3;
import java.util.EnumSet;
import java.util.Set;
/**
* builder模式的类层次结构
*/
public abstract class Pizeea {
//枚举类定义配料内容
public enum Topping {
HAM,
MUSHROOM,
ONLINE,
PEPPER,
SAUSAGE
}
final Set<Topping> toppings;
abstract static class Builder<T extends Builder<T>>{
//使用制定的集合类型,----创建一个空的枚举类集合
EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
//公共的添加辅料的方法。父类采用范型,更加灵活的接受子类的调用
public T addTopping(Topping topping){
toppings.add(topping);
return self();
}
abstract Pizeea build();
//所有的子类重载一个方法,并且返回this; 该方法的使用可以是子类进行方法链接,二不需要转换类型
protected abstract T self();
}
Pizeea(Builder<?> builder){
toppings = builder.toppings.clone();
}
}
package com.example.demo.effective_java.page3;
import java.util.Objects;
public class NuPizza extends Pizeea{
public enum Size{
SMALL,
MEDIUM,
LARGE;
}
private final Size size;
public static class Builder extends Pizeea.Builder<Builder> {
private final Size size;
//构造大小 方便在直接构造的时候直接构建特色的
public Builder(Size size) {
this.size = Objects.requireNonNull(size);
}
@Override
NuPizza build() {
return new NuPizza(this);
}
@Override
protected Builder self() {
return this;
}
}
NuPizza(Builder builder) {
super(builder);
size = builder.size;
}
}
package com.example.demo.effective_java.page3;
public class CalZone extends Pizeea{
private final boolean sauceInsise;
public static class Builder extends Pizeea.Builder<Builder> {
private boolean sauceInsise = false; //default
public Builder sauceInsise(){
//,默认为false ,只有在构建的时候才赋值false
sauceInsise =true;
return this;
}
@Override
public CalZone build() {
return new CalZone(this);
}
@Override
protected Builder self() {
return this;
}
}
CalZone(Builder builder) {
super(builder);//父类执行添加辅料的动作,子类执行自己的特色
sauceInsise = builder.sauceInsise;
}
}
总之,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Bulider是不错的选择。
第三条:通过私有构造器或者枚举来强化单例属性
该条具体不做分析,在设计模式的单例模式中会进行详细解释。
第四条 通过私有构造器来强化不可实例化的能力。
通常情况下,我们可以通过将构造器私有化来限制应用不可实例该对象