设计模式~Builder模式

83 阅读2分钟

1. 定义

  • 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

2. UML类图

image.png

  • Product:产品类
  • Builder:抽象Builder类,规范产品的组建,一般是由子类实现具体的组件过程
  • ConcreteBulider:抽象Builder类的实现类,实现抽象Builder类定义的所有方法,并且返回一个组建好的对象
  • Director: 统一组装流程(现实开发中,这个角色经常会被省略,直接用Builder类链式调用来进行对象的组装

3. 使用场景

  • 当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时
  • 相同的方法,不同的执行顺序,产生不同的事件结果时
  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时
  • 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用

4. 简单实现

  • 需求:建造一个房子,房子有地基、框架、门、窗、卫生间等属性,要求必须有地基和框架
  • 此处使用比较多的省略Director角色的Java实现
/**
 * 房子
 *
 * @author BTPJ  2022/1/13
 */
public class House {
    // 门
    private Object door;
    // 窗户
    private Object window;
    // 地基
    private Object foundation;
    // 框架
    private Object frame;
    // 卫生间
    private Object toilet;

    public static class Builder {
        private final House mHouse;

        public Builder() {
            mHouse = new House();
        }

        public Builder setDoor(Object door) {
            mHouse.door = door;
            return this;
        }

        public Builder setWindow(Object window) {
            mHouse.window = window;
            return this;
        }

        public Builder setFoundation(Object foundation) {
            mHouse.foundation = foundation;
            return this;
        }

        public Builder setFrame(Object frame) {
            mHouse.frame = frame;
            return this;
        }

        public Builder setToilet(Object toilet) {
            mHouse.toilet = toilet;
            return this;
        }

        /**
         * 构建器,核心就是对House对象的一些属性的判断,处理等
         *
         * @param builder Builder
         * @return House对象
         */
        public House build(Builder builder) {
            if (mHouse.foundation == null) {
                mHouse.foundation = new Object();
            }
            if (mHouse.frame == null) {
                mHouse.frame = new Object();
            }
            if (mHouse.door == null && mHouse.window != null) {
                mHouse.door = new Object();
            }
            if (mHouse.door != null && mHouse.window == null) {
                mHouse.window = new Object();
            }
            return mHouse;
        }
    }
}

// 链式使用
new Builder().setDoor(new Object()).setWindow(new Object()).build();
  • 上面只是一个简易的实现,但不禁要问我可以直接在House的set方法中return this(即House对象)啊,何必额外加个Builder呢,但假如说我要保证House的foundation必须set有值呢,当然这时候你可以直接给foundation属性初始化的时候就设置默认值,这的确也可以;但我假如有更严苛的要求:window和door要么都有要么都没有,这个时候或许你可能就无能为力了,这时Builder类的build方法的作用就体现出来了,它可以做一些属性的判断处理甚至是对属性的赋值先后顺序的控制

5. 源码中的使用场景

  • Android的AlertDialog对象的创建就使用了Builder模式

6. 优缺点

  • 优点:
    • 建造者独立,容易扩展
    • 良好的封装性,可以使客户端不必知道产品内部组成的细节
  • 缺点:
    • 产生多余的Build对象(Dirextor对象)