builder 设计模式

1、经典的Builder模式

Product

/**
 * 计算机抽象类, 即Product角色
 */
public abstract class Computer {

    protected String mBoard;
    protected String mDisplay;
    protected String mOS;

    public Computer() {
    }

    public void setBoard(String board) {
        mBoard = board;
    }

    public void setDisplay(String display) {
        mDisplay = display;
    }

    public abstract void setOS();

    @Override
    public String toString() {
        return "Computer{"
                + "mBoard='"
                + mBoard
                + '\''
                + ", mDisplay='"
                + mDisplay
                + '\''
                + ", mOS='"
                + mOS
                + '\''
                + '}';
    }
}
复制代码

作者:mundane
链接:https://juejin.im/post/5aa3dfd66fb9a028c42dd13a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Code
具体的Product
/**
 * 具体的Computer类
 */
public class Macbook extends Computer {

    public Macbook() {
    }

    @Override
    public void setOS() {
        mOS = "Mac OS X 10.10";
    }
}

作者:mundane
链接:https://juejin.im/post/5aa3dfd66fb9a028c42dd13a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Code

抽象Builder

/**
 * 抽象Builder类
 */
public abstract class Builder {

    public abstract void buildBoard(String board);

    public abstract void buildDisplay(String display);

    public abstract void buildOS();

    public abstract Computer create();

}

作者:mundane
链接:https://juejin.im/post/5aa3dfd66fb9a028c42dd13a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

ConcreteBuilder

/**
 * 具体的Builder类, MacbookBuilder
 */
public class MacbookBuilder extends Builder { private Computer mComputer = new Macbook(); @Override public void buildBoard(String board) { mComputer.setBoard(board); } @Override public void buildDisplay(String display) { mComputer.setDisplay(display); } @Override public void buildOS() { mComputer.setOS(); } @Override public Computer create() { return mComputer; } } 复制代码

 


作者:mundane
链接:https://juejin.im/post/5aa3dfd66fb9a028c42dd13a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 
/**
 * Director类, 负责构造Computer
 */
public class Director {

    Builder mBuilder;

    public Director(Builder builder) {
        mBuilder = builder;
    }

    public void construct(String board, String display) {
        mBuilder.buildBoard(board);
        mBuilder.buildDisplay(display);
        mBuilder.buildOS();
    }
}


作者:mundane
链接:https://juejin.im/post/5aa3dfd66fb9a028c42dd13a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
public class Main {

    public static void main(String[] args) {
        Builder builder = new MacbookBuilder();
        Director pcDirector = new Director(builder);
        pcDirector.construct("英特尔主板", "Retina 显示器");
        Computer macBook = builder.create();
        System.out.println("Computer Info: " + macBook.toString());
    }
}


作者:mundane
链接:https://juejin.im/post/5aa3dfd66fb9a028c42dd13a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

输出结果:

Computer Info: Computer{mBoard='英特尔主板', mDisplay='Retina 显示器', mOS='Mac OS X 10.10'}

可以看出, 经典的 Builder 模式重点在于抽象出对象创建的步骤,并通过调用不同的具体实现类从而得到不同的结果, 但是在创建过程中依然要传入多个参数, 不是很方便, 所以有了变种的Builder模式

2、变种的Builder模式

public class User {

    private final String firstName;     // 必传参数
    private final String lastName;      // 必传参数
    private final int age;              // 可选参数
    private final String phone;         // 可选参数
    private final String address;       // 可选参数

    private User(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }

    public static class UserBuilder {
        private final String firstName;
        private final String lastName;
        private int age;
        private String phone;
        private String address;

        public UserBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public UserBuilder address(String address) {
            this.address = address;
            return this;
        }

        public User build() {
            return new User(this);
        }
    }
}
使用
new
User.UserBuilder("王", "小二") .age(20) .phone("123456789") .address("亚特兰蒂斯大陆") .build();

唯一可能存在的问题就是会产生多余的Builder对象,消耗内存。然而大多数情况下我们的Builder内部类使用的是静态修饰的(static),所以这个问题也没多大关系。

由于Builder是非线程安全的,所以如果要在Builder内部类中检查一个参数的合法性,必需要在对象创建完成之后再检查。

public User build() {
  User user = new user(this);
  if (user.getAge() > 120) {
    throw new IllegalStateException(“Age out of range”); // 线程安全
  }
  return user;
}

上面的写法是正确的,而下面的代码是非线程安全的:

public User build() {
  if (age > 120) {
    throw new IllegalStateException(“Age out of range”); // 非线程安全
  }
  return new User(this);
}

猜你喜欢

转载自www.cnblogs.com/LittleSpring/p/11417463.html