1 前言
建造者模式属于建造者模式,它提供了一种创建对象的最佳方式。
在不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象,用户只需要给出指定复杂对象和内容,建造者模式按照顺序创建复杂对象。
既然是建造者模式。那么我们就用建造房屋来举例。假设我们建造房屋有4个步骤:
(1 )房屋设计 (2) 建造地基 (3) 铺设管道 (4) 粉刷房屋
其中这4个步骤就是我们抽象的Builder(图中序号2)
然后我们需要找具体的建造者也就是工人去建造房屋(图中序号3)
其次我们需要一个指挥者去指挥工人按照什么样的顺序去建造房屋(图中序号1)
最后生产出我们具体的产品(图中序号4)
2 Builder模式实现
2.1 Builder模式的常规实现
步骤一:创建抽象类(建造房屋的具体方法)
//建造者抽象的建造方法 public abstract class Builder { abstract void builderA(); //地基 abstract void builderB(); //钢筋工程 abstract void builderC(); //铺设电线 abstract void builderD(); //粉刷 //完工 得到具体的产品 abstract Product getProduct(); }
步骤二:创建产品类(具体的产品)
// 建造的产品 public class Product { private String buildA; private String buildB; private String buildC; private String buildD; public String getBuildA() { return buildA; } public void setBuildA(String buildA) { this.buildA = buildA; } public String getBuildB() { return buildB; } public void setBuildB(String buildB) { this.buildB = buildB; } public String getBuildC() { return buildC; } public void setBuildC(String buildC) { this.buildC = buildC; } public String getBuildD() { return buildD; } public void setBuildD(String buildD) { this.buildD = buildD; } @Override public String toString() { return "Product{" + "buildA='" + buildA + '\'' + ", buildB='" + buildB + '\'' + ", buildC='" + buildC + '\'' + ", buildD='" + buildD + '\'' + '}'; } }
步骤三: 创建具体的builder(具体实施产品的类)
//具体的建造者 public class Wroker extends Builder{ private Product product; public Wroker() { product = new Product(); } @Override void builderA() { product.setBuildA("地基"); System.out.println("地基"); } @Override void builderB() { product.setBuildB("钢筋工程"); System.out.println("钢筋工程"); } @Override void builderC() { product.setBuildC("铺设电线"); System.out.println("铺设电线"); } @Override void builderD() { product.setBuildD("粉刷房屋"); System.out.println("粉刷房屋"); } @Override Product getProduct() { return product; } }
步骤四: 创建指挥者(面向抽象类)
//指挥者 指挥工人构建工程 public class Director { //指挥工人按照顺序建造房子 public Product build(Builder builder){ builder.builderA(); builder.builderB(); builder.builderD(); builder.builderC(); return builder.getProduct(); } }
步骤五:测试
public class Test { public static void main(String[] args) { Director director = new Director(); Product build = director.build(new Wroker()); System.out.println(build.toString()); } }
测试结果:
上面的示例是Builder的常规用法,导演类Director在建造者模式中具有十分重要的作用,它用于指导构建者如何构建出产品。我们只需要控制工人来控制调用的先后顺序.向调用者返回一个完整的产品
2.2 Builder模式通过静态内部类实现
此次的实现方式我们省去指挥者这个角色。我们举个去吃麦当劳的例子。我们去吃麦当劳可以选择许多套餐。可以自己选择,同时也可以选择系统默认的套餐。
步骤一:创建一个Builder抽象类(选择套餐)
public abstract class Builder { abstract Builder builderA(String msg); //汉堡 abstract Builder builderB(String msg); //炸鸡 abstract Builder builderC(String msg); //可乐 abstract Builder builderD(String msg); //薯片 //完工 得到具体的产品 abstract Product getProduct(); }
步骤二:创建一个产品类(有默认套餐)
public class Product { //默认套餐 private String BuilderA = "汉堡"; private String BuilderB = "炸鸡"; private String BuilderC = "可乐"; private String BuilderD = "薯片"; public String getBuilderA() { return BuilderA; } public void setBuilderA(String builderA) { BuilderA = builderA; } public String getBuilderB() { return BuilderB; } public void setBuilderB(String builderB) { BuilderB = builderB; } public String getBuilderC() { return BuilderC; } public void setBuilderC(String builderC) { BuilderC = builderC; } public String getBuilderD() { return BuilderD; } public void setBuilderD(String builderD) { BuilderD = builderD; } @Override public String toString() { return "Product{" + "BuilderA='" + BuilderA + '\'' + ", BuilderB='" + BuilderB + '\'' + ", BuilderC='" + BuilderC + '\'' + ", BuilderD='" + BuilderD + '\'' + '}'; } }
步骤三: 创建一个实现Builder抽象类具体建造者
public class Wroker extends Builder { private Product product; public Wroker(){ product = new Product(); } @Override Builder builderA(String msg) { product.setBuilderA(msg); return this; } @Override Builder builderB(String msg) { product.setBuilderB(msg); return this; } @Override Builder builderC(String msg) { product.setBuilderC(msg); return this; } @Override Builder builderD(String msg) { product.setBuilderD(msg); return this; } @Override Product getProduct() { return product; } }
步骤四:测试
public class Test { public static void main(String[] args) { Wroker wroker = new Wroker(); Product product = wroker.builderA("香辣鸡腿堡") .getProduct(); System.out.println(product.toString()); } }
测试结果:
我们可以发现。这种方式较上一种方式更为的方便简单,可以还可以灵活的调用
建造者模式优点:
产品的建造和表示分离,实现了解耦。使用了建造者模式可以使客户端不必知道产品内部组成的细节
将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
具体建造者之间是相互独立的,这有利于系统的拓展。增加新的具体建造者无需修改原有类库的代码,符合开闭原则
建造者模式缺点:
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则适合使用建造者模式,因此其使用范围受到一定限制
如果产品内部变化复杂,可能会导致需要定义很多具体建造者来实现这种变化,导致系统变的很庞大。
以上只是部分内容,为了维护方便,本文已迁移到新地址:二十三种设计模式——建造者模式 – 编程屋