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:达到目标的惟一力量就是我的保持精力。