新闻资讯
Spring框架中的设计模式——建设者模式
建设者模式
建设者设计模式是属于创建对象模式三剑客的第一种模式。该模式用于简化复杂对象的构造。要理解这个概念,想象一个说明程序员简历的对象。在这个对象中,我们想存储个人信息(名字,地址等)以及技术信息(知识语言,已实现的项目等)。该对象的构造可能如下所示:
// with constructor
Programmer programmer = new Programmer("first name", "last name", "address Street 39", "ZIP code", "City", "Country", birthDateObject, new String[] {"Java", "PHP", "Perl", "SQL"}, new String[] {"CRM system", "CMS system for government"});
// or with setters
Programmer programmer = new Programmer();
programmer.setName("first name");
programmer.setLastName("last name");
// ... multiple lines after
programmer.setProjects(new String[] {"CRM system", "CMS system for government"});
Builder允许我们通过使用将值传递给父类的内部构建器对象来清楚地分解对象构造。所以对于我们这个程序员简历的对象的创建,构建器可以看起来像:
public class BuilderTest {
@Test
public void test() {
Programmer programmer = new Programmer.ProgrammerBuilder()
.setFirstName("F").setLastName("L")
.setCity("City").setZipCode("0000A").setAddress("Street 39")
.setLanguages(new String[] {"bash", "Perl"})
.setProjects(new String[] {"Linux kernel"}).build();
assertTrue("Programmer should be 'F L' but was '" + programmer + "'",
programmer.toString().equals("F L"));
}
}
class Programmer {
private String firstName;
private String lastName;
private String address;
private String zipCode;
private String city;
private String[] languages;
private String[] projects;
private Programmer(String fName, String lName, String addr, String zip, String city, String[] langs, String[] projects) {
this.firstName = fName;
this.lastName = lName;
this.address = addr;
this.zipCode = zip;
this.city = city;
this.languages = langs;
this.projects = projects;
}
public static class ProgrammerBuilder {
private String firstName;
private String lastName;
private String address;
private String zipCode;
private String city;
private String[] languages;
private String[] projects;
public ProgrammerBuilder setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public ProgrammerBuilder setLastName(String lastName) {
this.lastName = lastName;
return this;
}
public ProgrammerBuilder setAddress(String address) {
this.address = address;
return this;
}
public ProgrammerBuilder setZipCode(String zipCode) {
this.zipCode = zipCode;
return this;
}
public ProgrammerBuilder setCity(String city) {
this.city = city;
return this;
}
public ProgrammerBuilder setLanguages(String[] languages) {
this.languages = languages;
return this;
}
public ProgrammerBuilder setProjects(String[] projects) {
this.projects = projects;
return this;
}
public Programmer build() {
return new Programmer(firstName, lastName, address, zipCode, city, languages, projects);
}
}
@Override
public String toString() {
return this.firstName + " "+this.lastName;
}
}
可以看出,构建器后面隐藏了对象构造的复杂性,内部静态类接受链接方法的调用。在Spring中,我们可以在org.springframework.beans.factory.support.BeanDefinitionBuilder类中检索这个逻辑。这是一个允许我们以编程方式定义bean的类。我们可以在关于bean工厂后处理器的文章中看到它,BeanDefinitionBuilder包含几个方法,它们为AbstractBeanDefinition抽象类的相关实现设置值,比如作用域,工厂方法,属性等。想看看它是如何工作的,请查看以下这些方法:
public class BeanDefinitionBuilder {
/**
* The {@code BeanDefinition} instance we are creating.
*/
private AbstractBeanDefinition beanDefinition;
// ... some not important methods for this article
// Some of building methods
/**
* Set the name of the parent definition of this bean definition.
*/
public BeanDefinitionBuilder setParentName(String parentName) {
this.beanDefinition.setParentName(parentName);
return this;
}
/**
* Set the name of the factory method to use for this definition.
*/
public BeanDefinitionBuilder setFactoryMethod(String factoryMethod) {
this.beanDefinition.setFactoryMethodName(factoryMethod);
return this;
}
/**
* Add an indexed constructor arg value. The current index is tracked internally
* and all additions are at the present point.
* @deprecated since Spring 2.5, in favor of {@link #addConstructorArgValue}
*/
@Deprecated
public BeanDefinitionBuilder addConstructorArg(Object value) {
return addConstructorArgValue(value);
}
/**
* Add an indexed constructor arg value. The current index is tracked internally
* and all additions are at the present point.
*/
public BeanDefinitionBuilder addConstructorArgValue(Object value) {
this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(
this.constructorArgIndex++, value);
return this;
}
/**
* Add a reference to a named bean as a constructor arg.
* @see #addConstructorArgValue(Object)
*/
public BeanDefinitionBuilder addConstructorArgReference(String beanName) {
this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(
this.constructorArgIndex++, new RuntimeBeanReference(beanName));
return this;
}
/**
* Add the supplied property value under the given name.
*/
public BeanDefinitionBuilder addPropertyValue(String name, Object value) {
this.beanDefinition.getPropertyValues().add(name, value);
return this;
}
/**
* Add a reference to the specified bean name under the property specified.
* @param name the name of the property to add the reference to
* @param beanName the name of the bean being referenced
*/
public BeanDefinitionBuilder addPropertyReference(String name, String beanName) {
this.beanDefinition.getPropertyValues().add(name, new RuntimeBeanReference(beanName));
return this;
}
/**
* Set the init method for this definition.
*/
public BeanDefinitionBuilder setInitMethodName(String methodName) {
this.beanDefinition.setInitMethodName(methodName);
return this;
}
// Methods that can be used to construct BeanDefinition
/**
* Return the current BeanDefinition object in its raw (unvalidated) form.
* @see #getBeanDefinition()
*/
public AbstractBeanDefinition getRawBeanDefinition() {
return this.beanDefinition;
}
/**
* Validate and return the created BeanDefinition object.
*/
public AbstractBeanDefinition getBeanDefinition() {
this.beanDefinition.validate();
return this.beanDefinition;
}
}
原文链接:https://mp.weixin.qq.com/s/3AWW1OX5KwMDX4CM4c39kg
回复列表