程序员设计模式之JAVA

Builder Pattern

2020-07-24  本文已影响0人  93张先生

创建者模式

定义

Builder design pattern is an alternative way to construct complex objects and should be used only when we want to build different types of immutable objects using same object building process.

特征

和抽象工厂方法的区别

In one sentence, abstract factory pattern is the answer to "WHAT" and the builder pattern to "HOW".

fluent interface

A fluent interface is normally implemented by using method cascading (or method chaining).
创建者模式更像流式接口,方法链的模式

UML 类图

image.png

场景

构建一个不可变复杂对象,这样的构造方法很麻烦、容易出错;添加一个属性,使用构造方法的地方,都需要去修改。

public User (String firstName, String lastName, int age, String phone, String address){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    this.phone = phone;
    this.address = address;
}

当然可以写多个构造方法,也比较复杂和麻烦

public User (String firstName, String lastName, int age, String phone){ ... }
public User (String firstName, String lastName, String phone, String address){ ...  }
public User (String firstName, String lastName, int age){ ...   }
public User (String firstName, String lastName){ ...    }

样例

使用 Builder ,就很简单,容易扩展了。

public class User 
{
    //All final attributes
    private final String firstName; // required
    private final String lastName; // required
    private final int age; // optional
    private final String phone; // optional
    private final String address; // optional
 
    private User(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }
 
    //All getter, and NO setter to provde immutability
    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;
    }
 
    @Override
    public String toString() {
        return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.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;
        }
        //Return the finally consrcuted User object
        public User build() {
            User user =  new User(this);
            validateUserObject(user);
            return user;
        }
        private void validateUserObject(User user) {
            //Do some basic validations to check 
            //if user object does not break any assumption of system
        }
    }
}

使用方法

public static void main(String[] args) {
    User user1 = new User.UserBuilder("Lokesh", "Gupta")
    .age(30)
    .phone("1234567")
    .address("Fake address 1234")
    .build();
 
    System.out.println(user1);
 
    User user2 = new User.UserBuilder("Jack", "Reacher")
    .age(40)
    .phone("5655")
    //no address
    .build();
 
    System.out.println(user2);
 
    User user3 = new User.UserBuilder("Super", "Man")
    //No age
    //No phone
    //no address
    .build();
 
    System.out.println(user3);
}
 
Output:
 
User: Lokesh, Gupta, 30, 1234567, Fake address 1234
User: Jack, Reacher, 40, 5655, null
User: Super, Man, 0, null, null

优势

劣势

Existing implementations in JDK

All implementations of java.lang.Appendable are infact good example of use of Builder pattern in java. e.g.

java.lang.StringBuilder#append() [Unsynchronized class]

java.lang.StringBuffer#append() [Synchronized class]

java.nio.ByteBuffer#put() (also on CharBuffer, ShortBuffer, IntBuffer, LongBuffer, FloatBuffer and DoubleBuffer)

样例
StringBuilder builder = new StringBuilder("Temp");
String data = builder.append(1)
                .append(true)
                .append("friend")
                .toString();
System.out.println(data);
Output:
Temp1truefriend

MyBatis 中的应用

上一篇 下一篇

猜你喜欢

热点阅读