1 建造者模式介绍
建造者模式(Builder Pattern)也被称为生成器模式,是一步一步创建一个复杂对象的创建模型,它允许用户在不知道内部构建细节的情况下,可以更精确的控制对象的构造流程。
2 建造者模式定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
3 抽象工厂模式UML类图
建造者模式-UML类图角色介绍:
- Product:产品类。
- Builder:抽象Builder类,规范产品的组建,一般由子类实现。
- ConcreteBuilder:具体的Builder类。
- Director:统一组装过程
4 建造者模式使用示例
我们通过组装一部手机的例子来实现建造者模式。
产品类
我们将手机抽象成Phone
类,有一个型号和N多个部件(这里使用两个部件简单介绍下),提供3个方法分别来设置型号、摄像头和内存。
public class Phone {
//品牌型号
private String mBrand;
//像素
private String mCamera;
//运行内存
private String mRunMemory;
public void setmBrand(String brand) {
this.mBrand = brand;
}
public void setmCamera(String camera) {
this.mCamera = camera;
}
public void setmRunMemory(String runMemory) {
this.mRunMemory = runMemory;
}
@Override
public String toString() {
return mBrand + mCamera + mRunMemory;
}
}
Builder类组建
需要一套组装的模板,就是一个抽象的Builder
类,里面提供型号、摄像头和内存的方法,以及组装手机的方法:
public abstract class Builder {
public abstract void builderBrand(String brand);
public abstract void builderCamera(String camera);
public abstract void builderRunMemory(String runMemory);
public abstract Phone create();
}
我们通过实现抽象的Builder
类,来组装手机:
public class PhoneBuilder extends Builder {
private Phone mPhone = new Phone();
@Override
public void builderBrand(String brand) {
mPhone.setmBrand(brand);
}
@Override
public void builderCamera(String camera) {
mPhone.setmCamera(camera);
}
@Override
public void builderRunMemory(String runMemory) {
mPhone.setmRunMemory(runMemory);
}
@Override
public Phone create() {
return mPhone;
}
}
统一组装
我们统一在这里完成手机的组装:
public class Director {
Builder mBuilder = null;
public Director(Builder mBuilder) {
this.mBuilder = mBuilder;
}
public Phone construct(String bread, String camera,String memory){
mBuilder.builderBrand(bread);
mBuilder.builderCamera(camera);
mBuilder.builderRunMemory(memory);
return mBuilder.create();
}
}
客户端调用演示
那么我们就可以对手机进行命名和使用那些摄像头,以及使用多大的内存了。至于怎么组装我们完全不需要关心。
public class Client {
public static void main(String[] args) {
Builder builder = new PhoneBuilder();
Director director = new Director(builder);
Phone phone = director.construct("型号是:荣耀V20,", "摄像头是:索尼IMX 586, ", " 运行内存是:8G");
System.out.println(phone.toString());
}
}
输出结果是:
型号是:荣耀V20,摄像头是:索尼IMX 586, 运行内存是:8G
上述示例中,我们创建一个Phone
对象,而Director
类封装了构建复杂产品对象的过程,对外隐藏构建细节。Builder
和Director
一起将一份复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的对象。
链式调用
当然我们可以将Director
、Builder
角色直接省略掉,直接进行组装,这个就是我们常见到的链式调用,我们只需要将产品类改下,我们看下具体的代码实现:
public class Phone {
//品牌型号
private String mBrand;
//像素
private String mCamera;
//运行内存
private String mRunMemory;
public Phone setmBrand(String brand) {
this.mBrand = brand;
return this;
}
public Phone setmCamera(String camera) {
this.mCamera = camera;
return this;
}
public Phone setmRunMemory(String runMemory) {
this.mRunMemory = runMemory;
return this;
}
@Override
public String toString() {
return mBrand + mCamera + mRunMemory;
}
}
我们可以看到只要对setter方法进行改造都返回当前对象,即return this
这样我们就可以使用链式调用了
public class Client {
public static void main(String[] args) {
Phone phone = new Phone().setmBrand("型号是:荣耀V20,").setmCamera("摄像头是:索尼IMX 586 ,").setmRunMemory("运行内存是:8G。");
System.out.println(phone.toString());
}
}
输出的结果还是和上面的一样,这种方式不仅去除了Director
角色,整个结构更加简单,组装过程也更加简单,更容易控制。
5 建造者模式的使用场景
- 相同的方法,不同的执行顺序,产生不同的事件结果。
- 多个部件,都可以装配到一个对象中,但是产生的运行结果又不相同。
- 当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时。
- 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用。
6 总结
Builder
模式也是比较常用的,通常作为配置类的构建器将配置的构建和表示分离开来,同时也将配置从目标类中隔离出来,避免过多的setter
方法。Builder
模式比较常见的实现形式是通过调用链实现,这样是得代码更简洁、易懂。
优点:
- 良好的封装性,客户端可以不必知道产品内部组成细节。
- 建造者独立,容易扩展。
缺点:
- 产生多余的
Builder
对象以及Director
对象,消耗内存。
网友评论