Java 23种设计模式之构建者Builder模式

一:定义
建造者模式:指的是将一个简单对象的构建与它的示意拆散,使得同样的构建过程能够创立不同的示意,这样的设计模式称为建造者模式。
它是将一个简单的对象合成为多个简略的对象,而后一步一步构建而成。它将变与不变相拆散,即产品的组成部分是不变的,但每一部分是能够灵便抉择的
二.Builder模式的构造
1.产品角色(Product):它是蕴含多个组成部件的简单对象,由具体建造者来创立其各个零部件。
2.形象建造者(Builder):它是一个蕴含创立产品各个子部件的形象办法的接口,通常还蕴含一个返回产品的办法getResult().
3.具体的建造者(Concrete Builder):实现Builder接口,实现简单产品的各个部件的具体创立办法
4.指挥者(Director):它调用建造者对象中的部件结构与拆卸办法实现简单对象的创立,在指挥中不波及具体产品的信息

聚合关系:聚合关系是一种非凡的关联关系,聚合关系强调的是整体和局部的关系,其中局部能够脱离整体而存在。比方雁群和一只大雁的关系,就是聚合关系,大雁来到雁群还是能够独立存在的。
依赖关系:依赖关系是一种很弱的关系,个别是指一个类应用另一个类,这里学生捡到钱交给警察叔叔,学生和警察叔叔就是一种依赖关系
泛化关系:泛化关系在Java中也叫作继承关系,在UML中咱们用带空心三角形的直线来示意,咱们减少两个类,一个ConcreteBuilder1类,一个ConcreteBuilder2类,两个类均继承自Builder类
三:Builder模式的实现
1.咱们要建造一个产品Product--组装电脑
2.形象的Builder---装CPU,内存条,硬盘等形象的步骤
3.Builder的具体实现ConcreteBuilder -- 对上述形象步骤的实现,比方装i5CPU、8G内存条、1T硬盘
4.使用者Director -- 电脑装机人员
(1)产品的Product:电脑

public class Computer {    /*CPU*/    private String CPU;    /*内存*/    private String memory;    /*硬盘*/    private String hardDisk;    /*键盘*/    private String keyboard;    /*鼠标*/    private String mouse;//配置内存     public void setCPU(String CPU) {        this.CPU = CPU;    } //配置内存    public void setMemory(String memory) {        this.memory = memory;    }  //配置硬盘    public void setHardDisk(String hardDisk) {        this.hardDisk = hardDisk;    }  //配置键盘    public void setKeyboard(String keyboard) {        this.keyboard = keyboard;    }  //配置鼠标    public void setMouse(String mouse) {        this.mouse = mouse;    }    @Override    public String toString() {        return "Computer{" +                "CPU='" + CPU + '\'' +                ", memory='" + memory + '\'' +                ", hardDisk='" + hardDisk + '\'' +                ", keyboard='" + keyboard + '\'' +                ", mouse='" + mouse + '\'' +                '}';    }}

(2)形象的构建者Builder类通过接口实现,也能够通过抽象类

public interface ComputerConfigBuilder {    /*电脑组装个别都须要装置CPU、内存条、硬盘、键盘鼠标等,咱们把这一装置过程给形象进去,也就是这里的ComputerConfigBuilder ,至于具体装置什么须要其实现类来实现,另外其中还定义了一个获取Conputer的办法。*/    void setCPU();    void setMemery();    void setHardDisk();    void setKeyboard();    void setMouse();    //定义了一个获取产品Computer的办法返回的computer对象    Computer getComputer();}

应用抽象类能够这一应用

//这里须要理解抽象类和接口的区别public abstract class ComputerConfigBuilder1 {   public abstract void setCPU();    public abstract   void setMemery();    public abstract  void setHardDisk();    public abstract void setKeyboard();    public abstract void setMouse();    //定义了一个获取产品Computer的办法返回的computer对象    public abstract Computer getComputer();}

(3)创立一个低配版的套餐LowConfigBuilder ,让其实现ComputerConfigBuilder

public class LowConfigBuilder implements ComputerConfigBuilder {    //产品类Computer类    private Computer computer;    public LowConfigBuilder() {        //构造方法中创立产品类        this.computer = new Computer();    }    @Override    public void setCPU() {        computer.setCPU("i5");    }    @Override    public void setMemery() {        computer.setMemory("8G");    }    @Override    public void setHardDisk() {        computer.setHardDisk("500G");    }    @Override    public void setKeyboard() {        computer.setKeyboard("薄膜键盘");    }    @Override    public void setMouse() {        computer.setMouse("有线鼠标");    }/**具体实现类返回产品*/    @Override    public Computer getComputer() {        return computer;    }}

高配的组装类

public class HighConfigBuider  implements ComputerConfigBuilder{    private Computer mComputer;    public HighConfigBuider(){        this.mComputer = new Computer();    }    @Override    public void setCPU() {        mComputer.setCPU("i7");    }    @Override    public void setMemery() {        mComputer.setMemory("16G");    }    @Override    public void setHardDisk() {        mComputer.setHardDisk("1T");    }    @Override    public void setKeyboard() {        mComputer.setKeyboard("机械键盘");    }    @Override    public void setMouse() {        mComputer.setMouse("无线鼠标");    }    @Override    public Computer getComputer() {        return mComputer;    }}

(4)须要一个拆卸人员Director

public class Director {    private ComputerConfigBuilder mBuilder;    //这里setBuilder是拿到具体的建造者对象    public void setBuilder(ComputerConfigBuilder builder){        this.mBuilder=builder;    }    //拆卸人员director通过建造者拆卸具体的产品过程    public void createComputer(){        mBuilder.setCPU();        mBuilder.setMemery();        mBuilder.setHardDisk();        mBuilder.setKeyboard();        mBuilder.setMouse();    }    //拆卸人员拆卸好产品电脑返回    public Computer getComputer(){        return mBuilder.getComputer();    }}

(5)调用

public class ThirdTeenActivity extends AppCompatActivity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_third_teen);        Director director=new Director();//创立装机人员        director.setBuilder(new LowConfigBuilder());//通知装机人员的电脑配置,这里是低配版        director.createComputer();//装机人员开始组装       Computer computer= director.getComputer();//从装机人员获取组装好的电脑        System.out.println("低配电脑配置:"+computer.toString());        Log.d("aa",computer.toString());                Director director1=new Director();        director1.setBuilder(new HighConfigBuider());//高配组装        director1.createComputer();        Computer computer1=director1.getComputer();        System.out.println("高配电脑配置:"+computer1.toString());        Log.d("aa",computer1.toString());    }}//后果System.out: 低配电脑配置:Computer{CPU='i5', memory='8G', hardDisk='500G', keyboard='薄膜键盘', mouse='有线鼠标'}aa: Computer{CPU='i5', memory='8G', hardDisk='500G', keyboard='薄膜键盘', mouse='有线鼠标'}System.out: 高配电脑配置:Computer{CPU='i7', memory='16G', hardDisk='1T', keyboard='机械键盘', mouse='无线鼠标'}aa: Computer{CPU='i7', memory='16G', hardDisk='1T', keyboard='机械键盘', mouse='无线鼠标'}

四:变种Builder模式
须要创立一个不可变的Person对象,这个Person能够领有以下几个属性:名字、性别、年龄、职业、车、鞋子、衣服、钱、房子。其中名字和性别是必须有的

public class Person {    /*名字(必须)*/    private final String name;    /*性别(必须)*/    private final String gender;    /*年龄(非必须)*/    private final String age;    /*鞋子(非必须)*/    private final String shoes;    /*衣服(非必须)*/    private final String clothes;    /*钱(非必须)*/    private final String money;    /*房子(非必须)*/    private final String house;    /*汽车(非必须)*/    private final String car;    /*职业(非必须)*/    private final String career;    private Person(Builder builder) {        this.name = builder.name;        this.gender = builder.gender;        this.age = builder.age;        this.shoes = builder.shoes;        this.clothes = builder.clothes;        this.money = builder.money;        this.house = builder.house;        this.car = builder.car;        this.career = builder.career;    }    //动态外部类    public static class Builder{        private final String name;        private final String gender;        private String age;        private String shoes;        private String clothes;        private String money;        private String house;        private String car;        private String career;        public Builder(String name,String gender) {            this.name = name;            this.gender = gender;        }        public Builder age(String age) {            this.age = age;            return this;        }        public Builder car(String car) {            this.car = car;            return this;        }        public Builder shoes(String shoes) {            this.shoes = shoes;            return this;        }        public Builder clothes(String clothes) {            this.clothes = clothes;            return this;        }        public Builder money(String money) {            this.money = money;            return this;        }        public Builder house(String house) {            this.house = house;            return this;        }        public Builder career(String career) {            this.career = career;            return this;        }        //创立一个Person类的对象        public Person build(){            return new Person(this);        }    }//输入对象    @Override    public String toString() {        return "Person{" +                "name='" + name + '\'' +                ", gender='" + gender + '\'' +                ", age='" + age + '\'' +                ", shoes='" + shoes + '\'' +                ", clothes='" + clothes + '\'' +                ", money='" + money + '\'' +                ", house='" + house + '\'' +                ", car='" + car + '\'' +                ", career='" + career + '\'' +                '}';    }}//应用 Person person=new Person.Builder("Rocky", "男").age("18").build();        System.out.println("person"+person);                //后果        System.out: personPerson{name='Rocky', gender='男', age='18', shoes='null', clothes='null', money='null', house='null', car='null', career='null'}        

这里应用Person相似于产品,Builder外部类等价于构建者
因为这个Person对象是不可变的,所以毫无疑问咱们给他的所有属性都加了final润饰,当然如果没有不可变的需要也是能够不加的,
而后在Person类中定义一个外部类Builder,这个Builder外部类中的属性要和Person中的雷同,并且必须有的属性要用final润饰,避免这些属性没有被赋值,其余非必须的属性不能用final,因为如果加了final,就必须对其进行初始化,这样这些非必须的属性又变成必须的。
而后外部类中定义了一个构造方法,传入必须有的属性。其余非必须的属性都通过办法设置,每个办法都返回Builder对象本身。
最初定义了一个build办法,将Builder对象传入Person的公有构造方法,最终返回一个对象。
五:Android中网络申请OKHttp3创立申请信息的Request的源码
这里使用的变种的Builder构建者模型

因为这个Request 对象是不可变的,所有属性都加了final润饰public final class Request {//这里定义的属性是不可更改的  final HttpUrl url;  final String method;  final Headers headers;  final @Nullable RequestBody body;  final Object tag;  private volatile CacheControl cacheControl; // Lazily initialized.  Request(Builder builder) {    this.url = builder.url;    this.method = builder.method;    this.headers = builder.headers.build();    this.body = builder.body;    this.tag = builder.tag != null ? builder.tag : this;  }  //这里配置的url是为了内部获取url属性值  public HttpUrl url() {    return url;  }  public String method() {    return method;  }  public Headers headers() {    return headers;  }  public String header(String name) {    return headers.get(name);  }  public List<String> headers(String name) {    return headers.values(name);  }  public @Nullable RequestBody body() {    return body;  }  public Object tag() {    return tag;  }  public Builder newBuilder() {    return new Builder(this);  }  //打印申请的数据  @Override public String toString() {    return "Request{method="        + method        + ", url="        + url        + ", tag="        + (tag != this ? tag : null)        + '}';  }   public static class Builder {    HttpUrl url;//url链接    String method;//申请形式get,post,head等    Headers.Builder headers;//申请头    RequestBody body;//申请体    Object tag;//默认的申请形式是get申请    public Builder() {      this.method = "GET";      this.headers = new Headers.Builder();    }    Builder(Request request) {      this.url = request.url;      this.method = request.method;      this.body = request.body;      this.tag = request.tag;      this.headers = request.headers.newBuilder();    }//构建的url    public Builder url(HttpUrl url) {      if (url == null) throw new NullPointerException("url == null");      this.url = url;      return this;    }    。。。。。    //构建的申请头     public Builder header(String name, String value) {      headers.set(name, value);      return this;    }    //get申请     public Builder get() {      return method("GET", null);    }//head申请    public Builder head() {      return method("HEAD", null);    }//post申请    public Builder post(RequestBody body) {      return method("POST", body);    }    //这里build是创立Request对象,url是必须有的     public Request build() {      if (url == null) throw new IllegalStateException("url == null");      return new Request(this);    }    }    }        //应用     Request mRequest=new Request.Builder()                .get()                .url("https://www.baidu.com")                .build();    

长处:我能够不用晓得你的外部结构是怎么的,我能够间接应用Builder建造本人须要的客户端;代码清晰,易保护,易扩大;将结构和示意拆散,升高耦合
毛病:代码也可能不清晰,不易保护(怎么说:比方你的客户端实现了很多接口,当你每当批改接口的时候,每次都要对应批改你的客户端);应用不失当耗费内存

END:达到目标的惟一力量就是我的保持精力。