本文首发于顶格博客 Java设计模式之建造者模式。转载请注明出处
定义
建造者模式又称为生成器模式,是指将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。它允许用户只通过指定复杂对象的类型和内容就可以构建一个完整对象,用户不需要知道内部的具体构建细节。
角色
-
抽象建造者
抽象建造者角色,会定义顶层抽象的建造方法,用于暴露对外使用。 -
具体建造者
顾名思义,具体建造者会实现抽象建造者定义的方法,具体的实现不同对象的构建过程。具体建造者可以根据自身特性,赋予对象不同的属性,甚至增加额外属性。 -
指挥者
指挥者的作用在于,隔离客户与生产过程的同时负责控制产品的生成过程。针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象。
这一点不同于工厂方法。
工厂模式注重的是整体对象的创建方法,而建造者模式注重的是对象的创建过程,创建对象的过程方法可以在创建时自由调用。
- 产品对象
代码实现
代码实现以生产华为手机和苹果手机为例;
抽象产品类
/**
* 类名 Phone
* 描述 手机产品类
*
* @Author dgjava.com
* @Date 2020/5/6 17:46
* @Version 1.0
**/
@Data
public abstract class Phone {
protected String brand;
protected String screen;
protected String os;
protected String cpu;
protected String memory;
protected String cameras;
protected String network;
}
具体产品类
华为手机
/**
* 类名 Huawei
* 描述 华为手机
*
* @Author dgjava.com
* @Date 2020/5/6 18:04
* @Version 1.0
**/
@Data()
public class Huawei extends Phone {
private String mano;
public Huawei(){
this.brand="华为";
this.os = "安卓";
}
@Override()
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("品牌= ").append(this.brand).append("\n");
sb.append("系统= ").append(this.os).append("\n");
sb.append("内存= ").append(this.memory).append("\n");
sb.append("处理器= ").append(this.cpu).append("\n");
sb.append("摄像头= ").append(this.cameras).append("\n");
sb.append("屏幕= ").append(this.screen).append("\n");
sb.append("副卡= ").append(this.mano).append("\n");
sb.append("网络= ").append(this.network);
return sb.toString();
}
}
苹果手机
/**
* 类名 IPhone
* 描述 苹果手机
*
* @Author dgjava.com
* @Date 2020/5/6 18:04
* @Version 1.0
**/
@Data
public class IPhone extends Phone {
private String sensor;
public IPhone() {
this.brand = "苹果";
this.os = "IOS";
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("品牌= ").append(this.brand).append("\n");
sb.append("系统= ").append(this.os).append("\n");
sb.append("内存= ").append(this.memory).append("\n");
sb.append("处理器= ").append(this.cpu).append("\n");
sb.append("摄像头= ").append(this.cameras).append("\n");
sb.append("屏幕= ").append(this.screen).append("\n");
sb.append("传感器= ").append(this.sensor).append("\n");
sb.append("网络= ").append(this.network);
return sb.toString();
}
}
抽象建造者
/**
* 类名 PhoneBuilder
* 描述 手机建造接口
*
* @Author dgjava.com
* @Date 2020/5/6 18:12
* @Version 1.0
**/
public interface PhoneBuilder {
void buildCpu();
void buildScreen();
void buildCameras();
void buildMemory();
void buildNetwork();
void buildSensor();
void buildMano();
Phone build();
}
具体建造者
华为手机
/**
* 类名 HuaweiBulider
* 描述 华为手机建造实现类
*
* @Author dgjava.com
* @Date 2020/5/6 18:15
* @Version 1.0
**/
public class HuaweiBuilder implements PhoneBuilder {
private Huawei phone = new Huawei();
@Override
public void buildCpu() {
phone.setCpu("麒麟990");
}
@Override
public void buildScreen() {
phone.setScreen("6.5寸");
}
@Override
public void buildCameras() {
phone.setCameras("后置5摄像");
}
@Override
public void buildMemory() {
phone.setMemory("8+512G");
}
@Override
public void buildNetwork() {
phone.setNetwork("5G");
}
@Override
public void buildMano(){
phone.setMano("支持mini卡");
}
@Override
public void buildSensor() {
}
@Override
public Phone build() {
return phone;
}
}
苹果手机
/**
* 类名 IPhoneBulider
* 描述 苹果手机建造实现类
*
* @Author dgjava.com
* @Date 2020/5/6 18:15
* @Version 1.0
**/
public class IPhoneBuilder implements PhoneBuilder {
private IPhone phone = new IPhone();
@Override
public void buildCpu() {
phone.setCpu("A13");
}
@Override
public void buildScreen() {
phone.setScreen("6.4寸");
}
@Override
public void buildCameras() {
phone.setCameras("后置3摄像");
}
@Override
public void buildMemory() {
phone.setMemory("8+256");
}
@Override
public void buildNetwork() {
phone.setNetwork("4G");
}
@Override
public void buildSensor(){
phone.setSensor("3D-Touch");
}
@Override
public void buildMano() {
}
@Override
public Phone build() {
return phone;
}
}
指挥者
/**
* 类名 PhoneDirector
* 描述 产品建造指挥者
*
* @Author dgjava.com
* @Date 2020/5/6 18:26
* @Version 1.0
**/
public class PhoneDirector {
PhoneBuilder builder;
public Huawei builderHuawei() {
builder = new HuaweiBuilder();
builder.buildCameras();
builder.buildCpu();
builder.buildScreen();
builder.buildMemory();
builder.buildNetwork();
builder.buildMano();
return (Huawei) builder.build();
}
public IPhone builderIphone() {
builder = new IPhoneBuilder();
builder.buildCameras();
builder.buildCpu();
builder.buildScreen();
builder.buildMemory();
builder.buildNetwork();
builder.buildSensor();
return (IPhone) builder.build();
}
}
测试代码
public class BuilderDemo {
public static void main(String[] args) {
PhoneDirector director = new PhoneDirector();
Phone huawei = director.builderHuawei();
System.out.println("----- 华为手机 -----");
System.out.println(huawei);
System.out.println();
System.out.println("----- IPhone手机 -----");
Phone iphone = director.builderIphone();
System.out.println(iphone);
}
}
输出结果
优缺点
优点
-
封装解耦
在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。 -
隔离性好
每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。 -
过程清晰可控
可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
如上述示例,华为手机和苹果手机有独立的特性,分别实现互不干扰。 -
易扩展
增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
比如如果需要增加一种塞班手机,只需实现塞班手机对象,并且在指挥者中控制塞班手机的创建即可。
缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
使用场景
-
需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性;
比如:Java Bean对象有一种Builder模式,字段特别多,构造函数也特别多的情况。
-
需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
比如:如果是生产汽车,汽车分为燃油车、电动车和混合动力车。得先创建基本车型才能进一步构建油耗、功耗、充电时间等等。
-
对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类中。
-
隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。