builder模式分析

由于上一篇里的okhttp使用了builder模式,所以这里分析一下builder模式——建造者模式:

参看:https://www.cnblogs.com/lwbqqyumidi/p/3742562.html

其实建造者模式就是把各种属性都设置好,然后最后再进行类似于build的功能。所以属性特别多的时候建议用这种模式。

那么这些属性的设置有没有次序呢?

所以就分为两种情况:

1、通过Client、Director、Builder和Product形成的有次序的建造者模式

Builder负责Product类对象的具体过程构建

Director负责指导Build,要求Builder按照其指定的顺序去完成Produt的构造。

最后通过Builder返回建造后的结果

(1)建立房子类

package com.zs.zhao.buildertest.unstatic;

/**
 * Created by zhao on 2018/11/4.
 */

public class Room {
    private Window window;
    private Floot floot;

    public Window getWindow() {
        return window;
    }

    public void setWindow(Window window) {
        this.window = window;
    }

    public Floot getFloot() {
        return floot;
    }

    public void setFloot(Floot floot) {
        this.floot = floot;
    }
}

(2)建立build接口,也就是后续build要进行的一系列操作(盖房子啊,铺地砖啊、交房子啊什么的)

package com.zs.zhao.buildertest.unstatic;

/**
 * 工人接口,定义了工人所要进行的工作。他们负责进行具体部件如窗户,地板的建造。
 * 同时因为房子是民工建的,因此建设完成后由他把房子递交回房主
 * Created by zhao on 2018/11/4.
 */

public interface Builder {
    public void makeWindow();
    public void makeFloor();
    public Room getRoom();
}

(3)写出builder接口的实现类:

package com.zs.zhao.buildertest.unstatic;

/**
 * 具体的房屋建造工人类
 * Created by zhao on 2018/11/4.
 */

public class RoomBuilder implements Builder {
    private Room room=new Room();
    @Override
    public void makeWindow() {
        room.setWindow(new Window());
    }

    @Override
    public void makeFloor() {
    room.setFloot(new Floot());
    }

    @Override
    public Room getRoom() {
        return room;
    }
}

这样接下来我们只需要些个设计类来调用这些建造的方法就行了,这样就可以按顺序了。写好我们再调设计类。最后调用getRoom返回room对象就可以了,也就是下面的操作。

(4)

package com.zs.zhao.buildertest.unstatic;

/**
 * 定义房子设计师
 * Created by zhao on 2018/11/4.
 */

public class Designer {
    public void command(Builder builder){
        //先建造地板
        builder.makeFloor();
        //再建造窗户
        builder.makeWindow();
    }
}

 

(5)然后再写个调用的客户端:

package com.zs.zhao.buildertest.unstatic;

/**
 * Created by zhao on 2018/11/4.
 */

public class Client {
    public static void main(String[]args){
        //先找个工人来
        RoomBuilder roomBuilder = new RoomBuilder();
        //再找个设计师来
        Designer designer = new Designer();
        //工人按照设计师设计建造
        designer.command(roomBuilder);
        //工人向雇主交房子
        Room room = roomBuilder.getRoom();
    }
}

看到了吧,所有的操作顺序都被定义在roomBuilder里了。而顺序的保持是通过designer的command传入该builder保证的。那么无序的该怎么写呢?当然就不用设计类啦!直接把builder里方法的返回值还返回为该builder对象,这样就可以一直调下去啦。等全设置好了最后调个.build()。就可以返回我们在builder里设置的这个对象本身啦~(具体看下面,也就是第二种)

2、通过静态内部类等方式实现的无序的构造

package isstatic;

/**
 * Created by zhao on 2018/11/4.
 */

public class User {
    private String name;
    private int age;
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public static class Builder{
        private  User user=new User();
        public Builder setName(String name){
            user.setName(name);
            return this;
        }
        public Builder setAge(int age) {
             user.setAge(age);
             return this;
         }

        public Builder setAddress(String address) {
             user.setAddress(address);
             return this;
         }
         public User build(){
             return user;
         }
    }

    @Override
    public String toString() {
        return this.name+"\n"+this.age+"\n"+this.address;
    }
}

client:

package isstatic;

/**
 * Created by zhao on 2018/11/4.
 */

public class Client {
    public static void main(String[] args) {
        User user = new User.Builder()
                .setName("baobao")
                .setAge(1)
                .setAddress("dizhi")
                .build();
        System.out.println(user.toString());
    }
}

有没有很像okhttp和alertdialog啊。

那么我去扒一下okhttp的代码,我们来看一下下面这一段:

 Request request=new Request.Builder()
                .url("http://www.baidu.com")
                .header("User-Agent","Okhttp Example")
                .build();

那么按刚刚的推理,我们看一下Builder。

确实是个静态内部类。

那么既然是request,这个他的builder最后一定返回了一个通过这些方法传参后的request对象。

我们先看看.url方法

 /**
     * Sets the URL target of this request.
     *
     * @throws IllegalArgumentException if {@code url} is not a valid HTTP or HTTPS URL. Avoid this
     * exception by calling {@link HttpUrl#parse}; it returns null for invalid URLs.
     */
    public Builder url(String url) {
      if (url == null) throw new NullPointerException("url == null");

      // Silently replace web socket URLs with HTTP URLs.
      if (url.regionMatches(true, 0, "ws:", 0, 3)) {
        url = "http:" + url.substring(3);
      } else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
        url = "https:" + url.substring(4);
      }

      return url(HttpUrl.get(url));
    }

最后调用的url(HttpUrl.get(url))

public Builder url(HttpUrl url) {
      if (url == null) throw new NullPointerException("url == null");
      this.url = url;
      return this;
    }

最后这一个就相当于个set方法,把url存入了builder的url属性中。(和之前的例子不同,这里没有存入外面的request类的属性中,而是直接设置在了builder里 )

header也是存在了builder里。

设置完进行build()方法:

public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }

点进去看看new Request(this);

最后通过this对象(builder的)传入new Request(),然后把所有builder的属性传回给Request。但是为什么不是直接使用外面request属性进行存储而是要先用里面的。。这个我暂时也不知道为什么。如果有高手也希望进行下详解。谢谢~~~O(∩_∩)O。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值