Builder的介绍
将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。
Builder模式的适用性
多个部件或零件,都可以装配到一个对象中,但是产生的的运行结果又不相同时。
产品分类非常复杂,或者产品类中的调用顺序不同产生了不同作用。
当初始化一个对象非常复杂,如参数特别多,且很多参数都具有默认值时。
当构造过程必须允许被构造的对象有不同的表示时。
参与者
图和说明都是摘自《设计模式 —— 可复用面向对象软件的基础》
- Builder
——为创建一个Product对象的各个部件指定抽象接口 - ConcreteBuilder
——实现Builder的接口以构造和装配该产品的各个部件
——定义定义并明确他所创建的表示
——提供一个检索产品的接口 - Director
——构造一个使用Builder接口的对象 - Product
——表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义他的装配过程
——包含定义组成部分的类,包括将这些部件装配成最终产品的接口
协作
- 客户创建Director对象,并用他所想要的Builder对象进行装配
- 一旦产品部件被生成,导向器就会通知生成器
- 生成器处理导向器的请求,并将部件添加到该产品中
- 客户从生成器中检索产品
优缺点
- 优点:
- 良好的封装性,使用建造者模式可以使客户端不必知道产品内部组成的细节
- 创建者独立,容易扩展
- 缺点
- 产生多余的Buillder对象以及Director对象,消耗内存
Builder模式的小例子
方式一
Product
普通的产品类
public class Product {
private String CPU; //CPU
private String board; //主板
private String memory; //内存
private String hardDisk; //硬盘
private String display; //显示器
public String getCPU() {
return CPU;
}
public void setCPU(String CPU) {
this.CPU = CPU;
}
public String getBoard() {
return board;
}
public void setBoard(String board) {
this.board = board;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getHardDisk() {
return hardDisk;
}
public void setHardDisk(String hardDisk) {
this.hardDisk = hardDisk;
}
public String getDisplay() {
return display;
}
public void setDisplay(String display) {
this.display = display;
}
@Override
public String toString() {
return "Product{" +
"CPU='" + CPU + '\'' +
", board='" + board + '\'' +
", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' +
", display='" + display + '\'' +
'}';
}
}
Builder
Builder 接口,定义一组组建的方法,以及一个获取生成产品的方法
public interface Builder {
void setCPU();
void setBoard();
void setMemory();
void setHardDisk();
void setDisplay();
Product getProduct();
}
LowBuilder
Builder的具体实现类,其中一个产品
public class LowBuilder implements Builder{
private Product lowProduct;
public LowBuilder(){
this.lowProduct = new Product();
}
@Override
public void setCPU() {
lowProduct.setCPU("i5");
}
@Override
public void setBoard() {
lowProduct.setBoard("Intel");
}
@Override
public void setMemory() {
lowProduct.setMemory("8G");
}
@Override
public void setHardDisk() {
lowProduct.setHardDisk("256G");
}
@Override
public void setDisplay() {
lowProduct.setDisplay("三星");
}
@Override
public Product getProduct() {
return lowProduct;
}
}
HighBuilder
Builder的具体实现类,另外一个产品
public class HighBuilder implements Builder{
private Product highProduct;
public HighBuilder(){
this.highProduct = new Product();
}
@Override
public void setCPU() {
highProduct.setCPU("i7");
}
@Override
public void setBoard() {
highProduct.setBoard("Intel");
}
@Override
public void setMemory() {
highProduct.setMemory("16G");
}
@Override
public void setHardDisk() {
highProduct.setHardDisk("1T");
}
@Override
public void setDisplay() {
highProduct.setDisplay("三星");
}
@Override
public Product getProduct() {
return highProduct;
}
}
Director
Director类只调用Builder接口声明的方法完成组建产品的过程
public class Director {
private Builder mbuilder;
public Director(Builder builder){
this.mbuilder = builder;
}
public void construct(){
mbuilder.setCPU();
mbuilder.setBoard();
mbuilder.setMemory();
mbuilder.setHardDisk();
mbuilder.setDisplay();
}
public Product getProduct(){
return mbuilder.getProduct();
}
}
方式二
将部件的构建放入一个静态内部类中实现,静态内部类的属性和主类的属性保持一致,在内部类中设置属性。构造方法私有不对外公开,用户需要构建对象的时候,直接调用内部静态类的方法,采用链式编程完成产品的生成。
Person
public class Person {
/*名字(必须)*/
private final String name;
/*性别(必须)*/
private final String gender;
/*年龄(非必须)*/
private final String age;
/*鞋子(非必须)*/
private final String shoes;
/*衣服(非必须)*/
private final String clothes;
/*钱(非必须)*/
private final String money;
private Person(Builder builder){
this.name = builder.name;
this.gender = builder.gender;
this.age = builder.age;
this.shoes = builder.shoes;
this.clothes = builder.clothes;
this.money = builder.money;
}
public static class Builder{
private final String name;
private final String gender;
private String age;
private String shoes;
private String clothes;
private String money;
public Builder(String name ,String gender){
this.name = name;
this.gender = gender;
}
public Builder setAge(String age) {
this.age = age;
return this;
}
public Builder setShoes(String shoes) {
this.shoes = shoes;
return this;
}
public Builder setClothes(String clothes) {
this.clothes = clothes;
return this;
}
public Builder setMoney(String money) {
this.money = money;
return this;
}
public Person build(){
return new Person(this);
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", age='" + age + '\'' +
", shoes='" + shoes + '\'' +
", clothes='" + clothes + '\'' +
", money='" + money + '\'' +
", house='" + house + '\'' +
", car='" + car + '\'' +
", career='" + career + '\'' +
'}';
}
}
测试
public class TestBuilder {
public static void main(String[] args){
//new 一个LowBuilder对象
Builder lowBuilder = new LowBuilder();
//将对象传入给Director,告诉Director需要构建一个什么样的产品
Director director = new Director(lowBuilder);
//调用Director的生成产品的方法
director.construct();
//获取到生成的产品
System.out.println("低配电脑配置:"+director.getProduct().toString());
Builder highBuilder = new HighBuilder();
Director director1 = new Director(highBuilder);
director1.construct();
System.out.println("高配电脑配置"+director1.getProduct().toString());
//new 一个Person传入必要的属性参数,其余的属性都利用设置方法传入
Person person = new Person.Builder("wu","man")
.setAge("18")
.setShoes("hu")
.setClothes("A21")
.build();
System.out.println("persson:"+person.toString());
}
}