建造者模式
1 基本概念
- 建造者模式属于创建型模式,它提供了一种创建对象的最佳方式。
1、定义
- 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2、主要作用
- 在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
- 用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来)。
3、例子
- 工厂(建造者模式):负责制造汽车(组装过程和细节在工厂内)。
- 汽车购买者(用户):你只需要说出你要的星号(对象的类型和内容),然后直接购买就可以使用了(不需要知道汽车是怎么组装的)。
4、优点
- 产品的建造和表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节。
- 将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰。
- 具体的建造者类之间是相互独立的,这有利于系统的扩展。增加新的具体建造者无须修改原有类库的代码,符合“开闭原则”。
5、缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
6、应用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象具有共性。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
- 适合于一个具有较多的零件(属性)的产品(对象)的创建过程。
7、建造者与抽象工厂的比较
- 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥着类来指挥如何生成对象,包括对象的组织过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
- 如果将抽象工厂模式看出汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。
2 代码
1、案例1
Builder
package builder.demo01; /** * 抽象的建造者 */ public abstract class Builder { abstract void buildA(); abstract void buildB(); abstract void buildC(); abstract void buildD(); // 完工:得到产品 abstract Product getProduct(); }
Worker
package builder.demo01; /** * 具体的建造者:工人 */ public class Worker extends Builder { private Product product; public Worker() { product = new Product(); } @Override void buildA() { product.setBuildA("地基"); System.out.println("地基"); } @Override void buildB() { product.setBuildB("钢筋工程"); System.out.println("钢筋工程"); } @Override void buildC() { product.setBuildC("铺电线"); System.out.println("铺电线"); } @Override void buildD() { product.setBuildD("粉刷"); System.out.println("粉刷"); } @Override Product getProduct() { return product; } }
Director
package builder.demo01; /** * 指挥:核心。负责指挥构建一个工程。 */ public class Director { // 指挥工人按照顺序建房子。 public Product build(Builder builder) { builder.buildA(); builder.buildB(); builder.buildC(); builder.buildD(); return builder.getProduct(); } }
Product
package builder.demo01; /** * 产品:房子 */ 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 + '\'' + '}'; } }
MyTest
package builder.demo01; import org.junit.Test; public class MyTest { @Test public void test() { // 指挥 Director director = new Director(); // 指挥具体的工人完成产品 Product build = director.build(new Worker()); System.out.println(build); } }
2、案例2
Builder
package builder.demo02; /** * 建造者 */ 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(); }
Worker
package builder.demo02; /** * 具体的建造者 */ public class Worker extends Builder { private Product product; public Worker() { this.product = new Product(); } @Override Builder builderA(String msg) { product.setBuildA(msg); return this; } @Override Builder builderB(String msg) { product.setBuildB(msg); return this; } @Override Builder builderC(String msg) { product.setBuildC(msg); return this; } @Override Builder builderD(String msg) { product.setBuildD(msg); return this; } @Override Product getProduct() { return product; } }
Product
package builder.demo02; /** * 产品:套餐 */ public class Product { private String BuildA = "汉堡"; private String BuildB = "可乐"; private String BuildC = "薯条"; private String BuildD = "甜点"; public void setBuildA(String buildA) { BuildA = buildA; } public void setBuildB(String buildB) { BuildB = buildB; } public void setBuildC(String buildC) { BuildC = buildC; } public void setBuildD(String buildD) { BuildD = buildD; } @Override public String toString() { return "Product{" + "BuildA='" + BuildA + '\'' + ", BuildB='" + BuildB + '\'' + ", BuildC='" + BuildC + '\'' + ", BuildD='" + BuildD + '\'' + '}'; } }
MyTest
package builder.demo02; import org.junit.Test; public class MyTest { @Test public void test() { // 服务员 Worker worker = new Worker(); // 链式编程,在原来的基础上可以自由组合 Product product = worker .builderA("全家桶") .builderB("雪碧") .getProduct(); System.out.println(product); } }