精华内容
下载资源
问答
  • Builder 模式

    2016-03-24 20:45:23
    Builder 模式

    问题背景

    你要建造一所房子。大兴土木当然应该用很多劳力,但是知识分子也是必要的——要不房子结构会出问题,或者很难看。你需要一个设计师,这个人呢,知道怎么建房子。这个人会告诉你,建房子啊,应该先从底下开始(神说地基已经打好了),你得先弄弄地板,再弄弄墙,再在墙上打几个洞,一些当窗户,弄个接地气的当门。

    设计一

    所以我们有了一个无脑的设计。

    class House {
    
        private void buildFloor() {
            //
        }
    
        private void buildWall() {
            //
        }
    
        private void buildWindows() {
            //
        }
    
        private void buildDoor() {
            //
        }
    
        public House() {
            buildFloor();
            buildWall();
            buildWindows();
            buildDoor();
        }
    }

    不过其实也不是非常无脑,起码你没把四个 build* 函数的东西一股脑都填到构造函数里。

    设计一的问题

    那么这个设计怎么样呢?直接看起来好像还好。

    可是天要亡你。用户改需求啦!用户说,我有 100 套房子(壕),怎么能都建成一样的呢?我要这几套建成中式(China)的,这几套建成罗马式(Rome)的,那几套……

    设计师一听就头大了,这样一想原来的设计的确有问题:它的扩展性太差。不能支持“房子”的多样性。

    出现这种状况的原因是什么呢?我们看一看这个类有什么功能。第一、它建立了房子的各个部分;第二、它将各个部分组合起来。

    如果是一个简单一点的类的话,这样写其实没有多大问题,类有几个部分的话自然就应该这么构造。可是房子这个类比较复杂,它的种类太多也就是第一个功能部分要求扩展性;同时又有比较固定的构成,有了地板、墙壁、门等的构造方法之后,不论他们是什么风格的,组合起来的逻辑都是一样的。

    也就是说,房子这个类具有两个特性:

    1. 成分多样性高。
    2. 各个成分直接组成逻辑固定。

    对应着两项特性,构造房子这个工作,是由两个特征鲜明的部分组成:构建各个成分设计组装。在一个类中完成两项工作是不合适的,所以我们将把两个部分分开来做。

    Builder 模式

    首先我们来弄一个 Builder 类,用这个类做构建各个部分这件事情。

    package builder;
    
    import house.House;
    
    public class Builder {
    
        House house = new House();
    
        public void buildFloor();
    
        public void buildWall();
    
        public void buildWindows();
    
        public void buildDoor();
    
        public House getHouse();
    }
    

    类里的 getHouse(): void 就是得到最终房子的方法。请注意,这个 Builer 只是“民工”,它不懂设计,只知道每一部分怎么弄。

    “民工”需要一个设计师来指挥,设计师就是完成第二件事,设计组装的人。

    package designer;
    
    import builder.Builder;
    
    /**
     * @author plus7wist
     *
     */
    public class Designer {
    
        public void concreteHouse(Builder builder) {
            builder.buildFloor();
            builder.buildWall();
            builder.buildDoor();
            builder.buildWindows();
        }
    }

    代码里很明显可以看出,设计师其实什么都不干,它只是指挥 builder 进行工作,它的指挥体现出了设计的逻辑,而这一点 builder 又是不必操心的。

    这种两者合作的结构就是典型的 Builder 模式。

    扩展性

    我们再看看这个设计进行扩展的时候会怎么样。无论风格怎么改变,Designer 的逻辑都不变。对于多样变化的 Builder 我们很容易想到一种解决办法:利用多态,将原来的 Builder 变成抽象的。

    package builder;
    
    import house.House;
    
    public abstract class Builder {
    
        public abstract void buildFloor();
    
        public abstract void buildWall();
    
        public abstract void buildWindows();
    
        public abstract void buildDoor();
    
        public abstract House getHouse();
    }
    

    为了表示方便我们简要的写一下 House。用一个数组把成分的样子存起来。

    package house;
    
    import java.util.ArrayList;
    
    public class House {
        private ArrayList<String> parts = new ArrayList<String>();
    
        public void add(String part) {
            parts.add(part);
        }
    
        public void display() {
            for (int i = 0; i < parts.size(); ++i)
                System.out.print((i == 0 ? "" : ",") + parts.get(i));
            System.out.println();
        }
    }

    然后如果建中国风格的房子的话,就建一个ChinaHouseBuilder,继承自 Builder

    package concrete.builder;
    
    import house.House;
    import builder.Builder;
    
    /**
     * @author plus7wist
     *
     */
    public class ChinaHouseBuilder extends Builder {
    
        House chinaHouse = new House();
    
        @Override
        public void buildFloor() {
            chinaHouse.add("China Floor");
        }
    
        @Override
        public void buildWall() {
            chinaHouse.add("China Wall");
        }
    
        @Override
        public void buildWindows() {
            chinaHouse.add("China Windows");
        }
    
        @Override
        public void buildDoor() {
            chinaHouse.add("China Door");
        }
    
        @Override
        public House getHouse() {
            return chinaHouse;
        }
    }

    如果建罗马风格的房子的话,就建一个RomeHouseBuilder

    package concrete.builder;
    
    import house.House;
    import builder.Builder;
    
    /**
     * @author plus7wist
     *
     */
    public class RomeHouseBuilder extends Builder {
    
        House romeHouse = new House();
    
        @Override
        public void buildFloor() {
            romeHouse.add("Rome Floor");
        }
    
        @Override
        public void buildWall() {
            romeHouse.add("Rome Wall");
        }
    
        @Override
        public void buildWindows() {
            romeHouse.add("Rome Windows");
        }
    
        @Override
        public void buildDoor() {
            romeHouse.add("Rome Door");
        }
    
        @Override
        public House getHouse() {
            return romeHouse;
        }
    }

    如此一来,我们发现 Designer 的逻辑完全不用改——当真是个好的设计。

    最后我们看一眼怎么使用这个东西。

    package main;
    
    import builder.Builder;
    import house.House;
    import concrete.builder.*;
    import designer.Designer;
    
    /**
     * @author plus7wist
     *
     */
    public class Main {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Builder chinaHouseBuilder = new ChinaHouseBuilder();
            Builder romeHouseBuilder = new RomeHouseBuilder();
            Designer designer = new Designer();
            designer.concreteHouse(chinaHouseBuilder);
            designer.concreteHouse(romeHouseBuilder);
            House chinaHouse = chinaHouseBuilder.getHouse();
            House romeHouse = romeHouseBuilder.getHouse();
            chinaHouse.display();
            romeHouse.display();
        }
    }
    
    展开全文
  • Builder模式

    2020-12-03 13:22:48
    Builder模式 可以动态创建不同参数的对象 Builder模式的使用 User.builder() .seteMail("123123") .setPassword("12312312") .setPhone("1231231") .setUserName("12312312") .build(); Builder 创建 原对象 +...

    Builder模式

    可以动态创建不同参数的对象

    Builder模式的使用

    User.builder()
        .seteMail("123123")
        .setPassword("12312312")
        .setPhone("1231231")
        .setUserName("12312312")
        .build();
    

    Builder 创建

    原对象 + final 属性 + 构造函数(Builder builder) + builder函数(Builder对象)

    内部对象Builder + 与原对象一致的属性 + setter方法(返回值是Builder对象)+ build方法(新建原对象+返回原对象)

    public class User {
    	//final属性
        public final String userName;
        public final String password;
        public final String phone;
        public final String eMail;
    	//构造函数
        public User(Builder user) {
            this.userName = user.userName;
            this.password = user.password;
            this.phone = user.phone;
            this.eMail = user.eMail;
        }
    	//builder函数--新建Builder对象
        public static Builder builder(){
            return new Builder();
        }
        
        //--------Builder类-----------
        
        public static class Builder{
            public String userName;
            public String password;
            public String phone;
            public String eMail;
    
            //setter参数传入,并返回Builder对象
            public User.Builder setUserName(String userName) {
                this.userName = userName;
                return this;
            }
            
            //返回构造出的User对象
            public User build(){
                return new User(this);
            }
        }
    }
    
    展开全文
  • builder 模式

    2017-12-01 14:09:16
    什么是Builder模式? 为什么要使用Builder模式?它的优点是什么,那缺点呢? 什么情况下使用Builder模式? 关于Builder模式在代码中用的很多,比如AlertDialog, OkHttpClient等。一提到模式感觉像是一个很牛的招式...

    首先提出几个问题:

    • 什么是Builder模式?
    • 为什么要使用Builder模式?它的优点是什么,那缺点呢?
    • 什么情况下使用Builder模式?
      关于Builder模式在代码中用的很多,比如AlertDialog, OkHttpClient等。一提到模式感觉像是一个很牛的招式。用起来很炫。
      那先看看Builder是由什么组成,他的基本思想是什么
      这里写图片描述

    从类图中可以看出Builder 有四个角色
    - 抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。该接口定义两种方法,一种方法是建造方法,一般来说, 产品所包含的零件数目与建造方法的数目相符。
    - 具体创建者(Concrete Builder)角色: 担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。这个角色要完成的任务包括:1.实现抽象建造者Builder所生命的接口,给出一步一步地完成产品实例的操作。2.在建造过程完成后,提供产品的实例。
    - 导演者(Director)角色, 担任这个角色的类调用具体建造者角色以创建产品对象。
    - 产品(Product)角色:产品(Product)便是建造中的复杂对象。
    回到前面的问题,为什么要使用建造模式呢

    • 一个对象会有一些重要的性质,在它们没有恰当的值之前,对象不能作为一个完成的产品使用。
    • 一个对象的一些性质必须按照某个顺序赋值才有意义。

      这个时候,此对象相当于一个有待建造的产品,而对象的
      些性质相当于产品的零件,建造茶品的过程是建造零件的过
      程。由于建造零件的过程很复杂,因此,这些零件的建造过
      程往往被“外部化”到另一个称为建造者的对象里,建造者对
      象返还给客户端的是一个全部零件都建造完毕的产品对象。

      那么在什么情况下才应该使用建造模式

    • 需要生成的产品对象有复杂的内部结构,每一个成分本身也可以是对象,也可以仅仅是对象的的一个组成成分。

    • 需要生成的产品对象的属性相互依赖。建造模式可以强制实行一种分步骤进行的建造过程。因此,如果产品对象的一个属性必须在另一个属性被赋值之后才可以被赋值,使用建造模式便是一个很好的设计思想。
    • 在对象创建过程中会使用到系统中的其他一些对象,这些对象在产品对象的创建过程中不易得到。

    下面来看一下建造模式的优点

    • 建造模式的使用使得产品可以独立地变化。使用建造模式可以使客户端不必知道产品的内部组成的细节。
    • 每一个Builder都相对独立,而其他的Build无关。
    • 模式所建造的最终产品更容易于控制。
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,031
精华内容 4,812
关键字:

builder模式