由于需求的变更,有个项目的实体类的构造器变动频繁,即对象实例的组成属性变动频繁。
后来注意到StringBuilder和Swagger的ParameterBuilder的内部实现,发现可以非常灵活的构造出StringBuilder和ParameterBuider的实例,他们都是采用了构造者模式。
1. 以ParameterBuilder为例,构造对象实例方式如下(可以仅选择需要的属性进行赋值)
// 方式一 ParameterBuilder parameterBuilder = new ParameterBuilder(); parameterBuilder .description("description") .hidden(true) .name("name") .parameterAccess("parameterAccess") .parameterType("parameterType"); Parameter parameter = parameterBuilder.build(); // 方式二 Parameter builder = new ParameterBuilder() .name("name") .parameterType("paramterType") .allowMultiple(true) .defaultValue("defaultValue") .build();
2. ParameterBuilder的实现(属性与Parameter的一致,为每一个属性添加方法,重点是添加build方法构造Parameter,需要Parameter有一个全部属性的构造函数)
public class ParameterBuilder { private String name; private String description; private String defaultValue; private boolean required; private boolean allowMultiple; private AllowableValues allowableValues; private String paramType; private String paramAccess; private ResolvedType type; private ModelReference modelRef; private boolean hidden; private List<VendorExtension> vendorExtensions = Lists.newArrayList(); public ParameterBuilder() { } ParameterBuilder from(Parameter other) { return this.name(other.getName()).allowableValues(other.getAllowableValues()).allowMultiple(other.isAllowMultiple()).defaultValue(other.getDefaultValue()).description(other.getDescription()).modelRef(other.getModelRef()).parameterAccess(other.getParamAccess()).parameterType(other.getParamType()).required(other.isRequired()).type((ResolvedType)other.getType().orNull()).hidden(other.isHidden()).vendorExtensions(other.getVendorExtentions()); } public ParameterBuilder name(String name) { this.name = (String)BuilderDefaults.defaultIfAbsent(name, this.name); return this; } public ParameterBuilder description(String description) { this.description = (String)BuilderDefaults.defaultIfAbsent(description, this.description); return this; } public ParameterBuilder defaultValue(String defaultValue) { this.defaultValue = (String)BuilderDefaults.defaultIfAbsent(defaultValue, this.defaultValue); return this; } public ParameterBuilder required(boolean required) { this.required = required; return this; } public ParameterBuilder allowMultiple(boolean allowMultiple) { this.allowMultiple = allowMultiple; return this; } public ParameterBuilder allowableValues(AllowableValues allowableValues) { this.allowableValues = BuilderDefaults.emptyToNull(allowableValues, this.allowableValues); return this; } public ParameterBuilder parameterType(String paramType) { this.paramType = (String)BuilderDefaults.defaultIfAbsent(paramType, this.paramType); return this; } public ParameterBuilder parameterAccess(String paramAccess) { this.paramAccess = (String)BuilderDefaults.defaultIfAbsent(paramAccess, this.paramAccess); return this; } public ParameterBuilder type(ResolvedType type) { this.type = (ResolvedType)BuilderDefaults.defaultIfAbsent(type, this.type); return this; } public ParameterBuilder modelRef(ModelReference modelRef) { this.modelRef = (ModelReference)BuilderDefaults.defaultIfAbsent(modelRef, this.modelRef); return this; } public ParameterBuilder hidden(boolean hidden) { this.hidden = hidden; return this; } public ParameterBuilder vendorExtensions(List<VendorExtension> extensions) { this.vendorExtensions.addAll(BuilderDefaults.nullToEmptyList(extensions)); return this; } public Parameter build() { return new Parameter(this.name, this.description, this.defaultValue, this.required, this.allowMultiple, this.modelRef, Optional.fromNullable(this.type), this.allowableValues, this.paramType, this.paramAccess, this.hidden, this.vendorExtensions); } }
3. parameter的实现(主要是需要一个全部属性的构造函数)
public class Parameter { private final String name; private final String description; private final String defaultValue; private final Boolean required; private final Boolean allowMultiple; private final ModelReference modelRef; private final Optional<ResolvedType> type; private final AllowableValues allowableValues; private final String paramType; private final String paramAccess; private final Boolean hidden; private final List<VendorExtension> vendorExtensions; public Parameter(String name, String description, String defaultValue, boolean required, boolean allowMultiple, ModelReference modelRef, Optional<ResolvedType> type, AllowableValues allowableValues, String paramType, String paramAccess, boolean hidden, List<VendorExtension> vendorExtensions) { this.description = description; this.defaultValue = defaultValue; this.required = required; this.allowMultiple = allowMultiple; this.modelRef = modelRef; this.type = type; this.allowableValues = allowableValues; this.paramType = paramType; this.paramAccess = paramAccess; this.name = name; this.hidden = hidden; this.vendorExtensions = vendorExtensions; } public Optional<ResolvedType> getType() { return this.type; } public String getName() { return this.name; } public String getDescription() { return this.description; } public String getDefaultValue() { return this.defaultValue; } public Boolean isRequired() { return this.required; } public Boolean isAllowMultiple() { return this.allowMultiple; } public AllowableValues getAllowableValues() { return this.allowableValues; } public String getParamType() { return this.paramType; } public String getParamAccess() { return this.paramAccess; } public ModelReference getModelRef() { return this.modelRef; } public Boolean isHidden() { return this.hidden; } public List<VendorExtension> getVendorExtentions() { return this.vendorExtensions; } }
在Lombok中也有两个注解可以方便构造对象实例:@Builder和@Accessors(chain = true),但是使用这两个注解时,均不能构造出父类对象的属性,如下所示:
package cn.ucmed.pangu.lib.builders; import lombok.Builder; import lombok.Data; import lombok.experimental.Accessors; /** * @Description: * @author miaoying * @date 2019/3/1 */ public class Demo { public static void main(String[] args) { Test test = new Test().setName("name1"); System.out.println(test); // Test(name=name1, value=null) Test2 test2 = Test2.builder().name("name2").build(); System.out.println(test2); // Test2(name=name2, value=null) Son son = Son.builder().sonName("sonName").build(); // 不能设置parentName System.out.println(son); // Son(sonName=sonName) Daughter daughter = new Daughter().setDaughterName("name"); // 不能设置parentName System.out.println(daughter); // Daughter(daughterName=name) } } @Data @Accessors(chain = true) class Test { private String name; private String value; } @Data @Builder class Test2 { private String name; private String value; } @Data class Parent { private String parentName; } @Data @Builder class Son extends Parent { private String sonName; } @Data @Accessors(chain = true) class Daughter extends Parent { private String daughterName; }