如果一个类中有很多属性,为了避免构造函数的参数列表过长,影响代码的可读性和易用性,我们可以通过构造函数配合 set() 方法来解决。但是,如果存在下面情况中的任意一种,我们就要考虑使用建造者模式了。
- 我们把类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数就又会出现参数列表很长的问题。如果我们把必填属性通过 set() 方法设置,那校验这些必填属性是否已经填写的逻辑就无处安放了。
- 如果类的属性之间有一定的依赖关系或者约束条件,我们继续使用构造函数配合 set() 方法的设计思路,那这些依赖关系或约束条件的校验逻辑就无处安放了。
- 如果我们希望创建不可变对象,也就是说,对象在创建好之后,就不能再修改内部的属性值,要实现这个功能,我们就不能在类中暴露 set() 方法。构造函数配合 set() 方法来设置属性值的方式就不适用了。
工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。建造者模式是用来创建一种类型的复杂对象,可以通过设置不同的可选参数,“定制化”地创建不同的对象。
ConstructorArg
使用创建者模式重构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
| public class BeanDefinition {
private String id; private String className; private List<ConstructorArg> constructorArgs = new ArrayList<>(); private Scope scope = Scope.SINGLETON; private boolean lazyInit = false;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getClassName() { return className; }
public void setClassName(String className) { this.className = className; }
public List<ConstructorArg> getConstructorArgs() { return constructorArgs; }
public void setConstructorArgs(List<ConstructorArg> constructorArgs) { this.constructorArgs = constructorArgs; }
public Scope getScope() { return scope; }
public void setScope(Scope scope) { this.scope = scope; }
public boolean isLazyInit() { return lazyInit; }
public void setLazyInit(boolean lazyInit) { this.lazyInit = lazyInit; }
public boolean isSingleton() { return this.getScope().equals(Scope.SINGLETON); }
public static enum Scope { SINGLETON, PROTOTYPE }
public static class ConstructorArg { private boolean isRef = false; private Class type; private Object arg;
public boolean isRef() { return isRef; }
public Class getType() { return type; }
public Object getArg() { return arg; }
private ConstructorArg(boolean isRef, Class type, Object arg) { this.isRef = isRef; this.type = type; this.arg = arg; }
public static class Builder{ private boolean ref = false; private Class type; private Object arg;
public ConstructorArg build() { if (ref && type != null) { throw new RuntimeException("bean为ref类型时type不需要设置"); } if (!ref && (type == null || arg == null)) { throw new RuntimeException("bean不为ref类型时type和arg必须填写"); } return new ConstructorArg(ref, type, arg); }
public Builder setRef(boolean ref) { this.ref = ref; return this; }
public Builder setType(Class type) { this.type = type; return this; }
public Builder setArg(Object arg) { this.arg = arg; return this; } }
} }
public List<BeanDefinition> parse(InputStream inputStream) { List<BeanDefinition> beanDefinitions = new ArrayList<>(); try { Document document = reader.read(inputStream); Element beans = document.getRootElement(); Iterator beanIt = beans.elementIterator(); while(beanIt.hasNext()){ BeanDefinition beanDefinition = new BeanDefinition(); Element bean = (Element) beanIt.next();
List<Attribute> attributes = bean.attributes(); for (Attribute attribute : attributes) { if ("id".equals(attribute.getName())) { beanDefinition.setId(attribute.getValue()); } else if ("class".equals(attribute.getName())) { beanDefinition.setClassName(attribute.getValue()); } } Iterator argsIt = bean.elementIterator(); List<BeanDefinition.ConstructorArg> constructorArgs = new ArrayList<>(); while(argsIt.hasNext()){ BeanDefinition.ConstructorArg.Builder builder = new BeanDefinition.ConstructorArg.Builder(); Element arg = (Element) argsIt.next(); List<Attribute> argAttributes = arg.attributes(); for (Attribute attribute : argAttributes) { if ("type".equals(attribute.getName())) { try { builder.setType(Class.forName(attribute.getValue())); } catch (ClassNotFoundException e) { e.printStackTrace(); } builder.setArg(arg.getText()); } else if ("ref".equals(attribute.getName())) { builder.setRef(true); builder.setArg(attribute.getValue()); } } constructorArgs.add(builder.build()); beanDefinition.setConstructorArgs(constructorArgs); } beanDefinitions.add(beanDefinition); } } catch (DocumentException e) { throw new RuntimeException(e); } return beanDefinitions; }
|