堆积木,建造者模式

简介: 建造者模式,将其构建对象和组装成一个对象这两步给分开来。构建部分为(Builder)和组织部分(Director),实现了构建和装配的解耦。

0x01:建造者模式简介


将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

假如一个对象的构建很复杂,需要很多步骤。则可以使用建造者模式,将其构建对象和组装成一个对象这两步给分开来。构建部分为(Builder)和组织部分(Director),实现了构建和装配的解耦。


微信图片_20220502090855.png


主要角色如下:


Builder:为创建一个产品对象的各个部件指定抽象接口,一般由子类实现;


ConcreteBuilder:具体建造者,实现抽象类定义的所有方法,并且返回一个组建好的产品对象;


Director:为指挥者 / 导演类,负责安排已有模块的组装顺序,然后告诉Builder开始建造;


Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。


0x02:建造者模式实现


Product:要被构建的产品


public class Product {
private List<String> parts = new ArrayList<String>();
public void addPart(String part) {
        parts.add(part);
    }
public void show(){
if(!parts.isEmpty()){
            parts.forEach(e -> {
System.out.println( e );
            });
        }
    }
}


Director:调用具体建造者进行产品构建


public class Director {
public void construct(Builder builder) {
        builder.buildPartA();
        builder.buildPartB();
    }
}


Builder:建造者抽象接口


public interface Builder {
void buildPartA();        //产品的A部件
void buildPartB();        //产品的B部件
Product getResult();    //组装产品建造后的结果
}


具体建造者ConcreteBuilder:有几个产品类就有几个具体的建造者,而且这多个产品类具有相同的接口或抽象类。


public class ConcreteBuilder1 implements Builder {
private Product product = new Product();
//设置产品零件
@Override
public void buildPartA() {
        product.addPart("ConcreteBuilder1>>部件A");
    }
@Override
public void buildPartB() {
        product.addPart("ConcreteBuilder1>>部件B");
    }
//组建一个产品
@Override
public Product getResult() {
return product;
    }
}


public class ConcreteBuilder2 implements Builder {
private Product product = new Product();
//设置产品零件
@Override
public void buildPartA() {
        product.addPart("ConcreteBuilder2>>部件A");
    }
@Override
public void buildPartB() {
        product.addPart("ConcreteBuilder2>>部件B");
    }
//组建一个产品
@Override
public Product getResult() {
return product;
    }
}


建造者模式测试代码


public class Client {
public static void main(String[] args) {
Director director = new Director();
Builder builder1 = new ConcreteBuilder1();
Builder builder2 = new ConcreteBuilder2();
//指挥者用ConcreteBuilder1的方法来建造产品
        director.construct(builder1);
Product product1 = builder1.getResult();
        product1.show();
//指挥者用ConcreteBuilder2的方法来建造产品
        director.construct(builder2);
Product product2 = builder2.getResult();
        product2.show();
    }
}


可以看出建造者模式具有以下特点:


良好的封装性:建造者对客户端屏蔽了产品内部组成的细节,客户端不用关心每一个具体的产品内部是如何实现的。


符合开闭原则


便于控制细节风险:由于建造者是相互独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。


0x03:建造者模式在JDK中运用


在JDK中,最经典的建造者模式的运用是StringBuilder和StringBuffer,这两个类最主要的区别就是StringBuilder线程不安全,StringBuffer线程安全。下面与StringBuilder源码讲解一下,建造者模式在JDK中的运用。


Appendable 接口定义了多个 append 方法(抽象方法),即 Appendable 为抽象建造者(Builder),定义了抽象方法


public interface Appendable {
    Appendable append(CharSequence csq) throws IOException;
    Appendable append(CharSequence csq, int start, int end) throws IOException;
    Appendable append(char c) throws IOException;
}


AbstractStringBuilder 实现了 Appendable 接口方法所有append()方法,俨然AbstractStringBuilder 已经是就建造者,只是是一个抽象类AbstractStringBuilder ,不能实例化


abstract class AbstractStringBuilder implements Appendable, CharSequence {
@Override
public AbstractStringBuilder append(CharSequence s) {
if (s == null)
return appendNull();
if (s instanceof String)
return this.append((String)s);
if (s instanceof AbstractStringBuilder)
return this.append((AbstractStringBuilder)s);
return this.append(s, 0, s.length());
    }
@Override
public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
            s = "null";
if ((start < 0) || (start > end) || (end > s.length()))
throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", s.length() "
                + s.length());
int len = end - start;
        ensureCapacityInternal(count + len);
for (int i = start, j = count; i < end; i++, j++)
            value[j] = s.charAt(i);
        count += len;
return this;
    }
@Override
public AbstractStringBuilder append(char c) {
        ensureCapacityInternal(count + 1);
        value[count++] = c;
return this;
    }
// 省略
}


StringBuilder 既充当了指挥者角色(Director),同时也充当了具体的建造者(ConcreteBuilder),建造方法的实现是由 AbstractStringBuilder 完成,而 StringBuilder 继承了 AbstractStringBuilder


public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
    }
//其他省略
}


从StringBuilder代码上看,大部分方法都继承与AbstractStringBuilder,虽然是重写,但是还是直接调用了AbstractStringBuilder类中非方法,只是返回对象不太一样,StringBuilder类返回的对象就是当前创建的对象this本身(Product)。


另外,MyBatis框架中也大量使用建造者模式,如果想了解MyBatis框架中什么运用建造者模式的,可以阅读下MyBatis的源码。

相关文章
|
设计模式 算法 Java
JAVA设计模式13:模版方法模式,将一些步骤延迟到子类中实现
JAVA设计模式13:模版方法模式,将一些步骤延迟到子类中实现
|
4月前
|
设计模式
**工厂模式与抽象工厂模式**都是创建型设计模式,用于封装对象创建,减少耦合
【6月更文挑战第23天】**工厂模式与抽象工厂模式**都是创建型设计模式,用于封装对象创建,减少耦合。工厂模式专注于单个对象,通过具体工厂创建具体产品,适用于简单对象创建;抽象工厂则关注一系列相关产品,提供创建一族对象的接口,适用于处理多个不兼容产品族。选择模式基于问题域的复杂性,单个产品需求时用工厂模式,多产品族时用抽象工厂模式。
30 5
|
2月前
|
设计模式 存储 缓存
单例模式与工厂方法模式之间的差异
【8月更文挑战第24天】
42 0
|
3月前
|
设计模式 算法
交易链路设计原则&模式问题之中介者(Mediator)方法设计模式是什么,如何解决
交易链路设计原则&模式问题之中介者(Mediator)方法设计模式是什么,如何解决
|
设计模式 算法
使用工厂模式、策略模式、门面模式、单例模式、责任链模式、装饰者模式和访问者模式来实现红包雨(一)
使用工厂模式、策略模式、门面模式、单例模式、责任链模式、装饰者模式和访问者模式来实现红包雨
|
算法
使用工厂模式、策略模式、门面模式、单例模式、责任链模式、装饰者模式和访问者模式来实现红包雨(二)
使用工厂模式、策略模式、门面模式、单例模式、责任链模式、装饰者模式和访问者模式来实现红包雨
|
设计模式
大话设计模式——建造者模式类图分析
大话设计模式——建造者模式类图分析
|
设计模式 Java
JAVA设计模式16:职责链模式,轻松解耦发送者和接收者
JAVA设计模式16:职责链模式,轻松解耦发送者和接收者
146 0
|
设计模式 XML C++
设计模式之单例、工厂、发布订阅者模式
保证一个类仅有一个实例,并提供一个该实例的全局访问点
|
存储 设计模式
【设计模式】【第四章】【订单状态流转】【状态模式 + 享元模式+模板方法模式】
【设计模式】【第四章】【订单状态流转】【状态模式 + 享元模式+模板方法模式】
116 0