建造者设计模式

1.需求入手

1.1盖房子的需求

1.建房子的过程:打桩 => 砌墙 => 封顶。

2.房子的样式有很多种:如普通防痱子,高楼,别墅,各种房子的建造过程虽然一样,但是要求不一样(也就是建造的大步骤都是一致的,但是建造出来的模样是不同的,即要求都是不同的)

3.编写程序完成需求。

1.2传统方式实现需求

1.2.1UML类图设计

主要是抽象出来一个抽象类,作为上层的类,使用底层的两个类去基层这个上层抽象类,客户端去依赖使用这两个实现的类。

但是这个设计是具有一定的问题的,主要是在于,将建造房子的过程和产品进行耦合在了一起,耦合性比较强 => 比较好的设计应该是产品和产品建造的过程进行抽离才是比较好的解决方式,这样才可以进行解耦合。

1.2.2实现代码

1.2.2.1抽象房子类

抽象房子类主要是进行抽象定义主流程进行使用的。

抽象基类主要是进行定义了抽象流程(打桩/砌墙/封顶)这些流程都是使用在抽象基类中定义的抽象方法,这些方法主要是交给子类进行实现使用 => 流程一样但是每个派生类的具体实现是不一样的。

build则是进行定义的非抽象方法,这个非抽象方法进行固定了抽象方法的流程调用,方便让派生类直接调用使用。

java 复制代码
/**
 * 抽象房子
 */
public abstract class AbstractHouse {

    public abstract void buildBasic();

    public abstract void buildWalls();

    public abstract void roofed();

    public void build() {
        buildBasic();
        buildWalls();
        roofed();
    }
    
}
1.2.2.2抽象房子类的实现类

普通房子:

java 复制代码
/**
 * 普通房子
 */
public class CommonHouse extends AbstractHouse {
    @Override
    public void buildBasic() {
        System.out.println("普通房子进行打桩");
    }

    @Override
    public void buildWalls() {
        System.out.println("普通房子进行砌墙");
    }

    @Override
    public void roofed() {
        System.out.println("普通房子进行封顶");
    }
}

高档房子:

java 复制代码
/**
 * 高端房子
 */
public class HighBuilding extends AbstractHouse {

    @Override
    public void buildBasic() {
        System.out.println("高端房子进行打桩");
    }

    @Override
    public void buildWalls() {
        System.out.println("高端房子进行砌墙");
    }

    @Override
    public void roofed() {
        System.out.println("高端房子进行封顶");
    }
}

1.3优缺点和更优的解决方案

1.3.1优点

优点:便于理解,简单易操作。

1.3.2缺点

设计的程序结构,过于简单,没有设计缓存层对象,程序的扩展和维护不好。也就是说,这种设计方案,将产品(房子)和创建产品的过程(建房子的流程)封装在一起了,耦合性增强了。

所以要进行做的就是:将产品和创建产品的流程进行解耦合。

1.3.3解决方案

使用建造者模式 => 将产品和产品创建过程进行解耦合。

2.建造者模式

2.1建造者模式的四个角色

1.Product(产品角色):一个具体的产品角色。

2.Builder(抽象建造者):创建一个Product对象的各个部件指定的接口。

3.ConcreateBuilder(具体建造者):实现接口,构建和装配各个组件。

4.Director(指挥者):构建一个使用Builder接口的对象。它主要用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象生产的过程;二是:负责控制产品对象的生产过程。

2.2建造者模式原理类图

2.3建造者模式优化需求

2.3.1UML类图设计

这个设计就是比较不错的,House是产品,HouseBuilder是一个抽象嘞,进行组合了一个House并且进行定义了整个抽象他流程和制定了抽象流程调用顺序的建造方法,使用一些类进行实现HouseBuilder对象,想要创建什么类型的对象就调用哪个实现类进行构造创建。

一个HouseBuilder可以进行建造出来一个House。

将HouseBuilder进行聚合到HouseDirect中,HouseDirect是负责进行调用需要的HouseBuilder进行构造产品的。

要点:美妙的三层解耦,解耦出了产品曾,建造层,调用层,是一个解耦过程。

2.3.2产品类

定义一个产品House类,这个产品的对象都是通过指挥者进行调用建造层进行构造出来一个产品对象。

java 复制代码
/**
 * 产品 -> Product
 */
public class House {
    private String basis;
    private String wall;
    private String roofed;

    public String getBasis() {
        return basis;
    }

    public void setBasis(String basis) {
        this.basis = basis;
    }

    public String getWall() {
        return wall;
    }

    public void setWall(String wall) {
        this.wall = wall;
    }

    public String getRoofed() {
        return roofed;
    }

    public void setRoofed(String roofed) {
        this.roofed = roofed;
    }
}

2.3.3建造层

2.3.3.1抽象建造层
java 复制代码
/**
 * 抽象的建造者
 */
public abstract class HouseBuilder {

    protected House house = new House();

    // 将建造的流程写好, 抽象的方法
    public abstract void buildBasic();
    public abstract void buildWalls();
    public abstract void roofed();
    // 房子建好之后, 将建造好的房子(产品)进行返回
    public House buildHouse() {
        return house;
    }

}
2.3.3.2实现建造层

使用不同的实现层可以进行建造不同的房子。

建造普通房子的建造层:

java 复制代码
/**
 * 普通的房子
 */
public class CommonHouse extends HouseBuilder {
    @Override
    public void buildBasic() {
        System.out.println("普通房子进行打桩");
    }

    @Override
    public void buildWalls() {
        System.out.println("普通房子进行砌墙");
    }

    @Override
    public void roofed() {
        System.out.println("普通房子进行封顶");
    }
}

建造高端房子的建造层:

java 复制代码
/**
 * 高端房子
 */
public class HighBuilding extends HouseBuilder {
    @Override
    public void buildBasic() {
        System.out.println("高端房子进行打桩");
    }

    @Override
    public void buildWalls() {
        System.out.println("高端房子进行砌墙");
    }

    @Override
    public void roofed() {
        System.out.println("高端房子进行封顶");
    }
}

2.3.4指挥层

指挥层就是让客户端进行调用指挥者,指挥者去调用不同的HouseBuider中的流程进行建造出不同的产品,返回给客户端。

java 复制代码
/**
 * 指挥者
 */
public class HouseDirector {

    private HouseBuilder houseBuilder = null;

    // 构造器传入HouseBuilder
    public HouseDirector(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    // 通过setter 传入houseBuilder
    public void setHouseBuilder(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    // 处理建造房子的流程,交给指挥者
    public House constructHouse() {
        houseBuilder.buildBasic();
        houseBuilder.buildWalls();
        houseBuilder.roofed();
        return houseBuilder.buildHouse();
    }

}

3.建造者模式的应用

JDK内置的SpringBuilder中进行使用到了建造者模式。

3.1StringBuilder如何进行使用的建造者模式

3.1.1从UML图的角度进行理解

设计模式是一种思想,并不会局限于任何编码的形式,有些高手在进行设计的时候,当时还没有这个设计模式/高手根本就没想用这种设计模式,但是就是无形中写出了这种设计模式,反正就是比较叼,高手并不会拘泥于某种形式,总是会在无形中去利用到这种思想。

在下面个UML层次中,Appendable是一个抽象接口,主要是进行声明出来各种append抽象方法。其实就是充当一个建造层的底层抽象者。

AbstractStringBuilder其实是进行实现抽象方法的类,虽然是一个抽象类,但是里面进行实现了各种各样的append抽象方法,只是这个类不能被实例化而已。其实就是充当一个建造者的上层实现者。

StringBuilder就十分有意思了,它是一个产品,同时也是一个指挥者,进行通过实现AbstractStringBuilder类,调用AbstrtactStringBuilder中的方法(建造者中的方法),进行实现建造对象返回生产对象的功能,生产出的对象就是自己,自己既担任了指挥层,也担任了产品层。

3.1.2梳理一下其中的责任担当

Appendable:建造者底层抽象接口,进行声明建造方法抽象接口的。

AbstractStringBuilder:建造者上层实现类,进行实现了具体的建造方法。

StringBuilder:指挥者和产品。

4.建造者设计模式小结

1.客户端(使用程序)不必知道产品内部的组成细节,将产品本身和产品创建的过程解耦,使得相同的创建过程可以创建出不同的产品对象。

要点:将产品和产品生产的具体过程进行解耦合。

2.每一个具体建造者都相对独立,而与其它建造者无关,因此可以很方便的替代为具体建造者和新增其它建造者(指挥者可以使用各种各样的建造者,非常容易进行扩展)每用户使用不同的具体建造者可以得到不同的产品对象。

要点:指挥者和建造者分层,所以方便进行扩展,可以新增各种各样的建造者。

3.可与更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。

要点:产品的创建过程被解耦了到专门的建造者中,更加职责分明,方便进行控制。

4.增加新的具体建造者无需修改原有类库的代码,指挥者列针对抽象建造建造者类编程,系统扩展方便,符合开闭原则。

要点:固定抽象,上层使用者(指挥者)利用抽象进行编程,系统扩展方便,符合开闭原则(扩展开放时,由于使用者依赖于抽象,不会出现创建新的提供者后,使用者要进行更改代码的情况)

5.建造者模式所创建的产品一般具有较多共同点,其组成部分相似,如果产品之间差异性很大,则不适合使用建造者模式,因此使用范围会受到一定的限制。

要点:建造者模式适合创建的产品的组成结构相似,每个结构可有不同的产品,不适合结构上差异很大的产品。

6.如果产品内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大(实际的建造者过多),因此在这种情况下,要考虑是否选择使用建造者模式。

要点:需要创建的产品类别太多,就会导致系统比较庞大。

7.抽象工厂模式VS建造者模式

抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列的产品:具有不同分类维度产品组合,采用抽象工厂模式不需要关心构建过程,只需要关心什么产品由什么工厂生产即可。而建造者模式则是要求按指定的蓝图建造产品,它的主要目的是通过组装零配件而生产一个新产品。

要点:抽象工厂设计模式是使用不同的工厂创建不同的的对象(在类级别,抽象工厂的高度在类级别,是实实在在类结构上不同的对象)。建造者模式是对象级别的,是结构上相同,组成成分上不同的产品创建出来。

相关推荐
KhalilRuan9 分钟前
浅谈——C++和C#差异
开发语言·c++·c#
Reggie_L1 小时前
spring-cloud概述
java
遗憾随她而去.1 小时前
js面试题 高频(1-11题)
开发语言·前端·javascript
贾修行1 小时前
深入浅出理解 Reactor:响应式编程的利器
java·reactor
Dxy12393102164 小时前
Python观察者模式详解:从理论到实战
开发语言·python·观察者模式
hqxstudying4 小时前
J2EE模式---前端控制器模式
java·前端·设计模式·java-ee·状态模式·代码规范·前端控制器模式
不写八个7 小时前
GoLang教程005:switch分支
开发语言·后端·golang
ZeroToOneDev7 小时前
Java(LinkedList和ArrayList底层分析)
java·开发语言
吃饭只吃七分饱8 小时前
C++第8章:IO库
开发语言·c++
没有bug.的程序员8 小时前
JAVA面试宝典 -《 架构演进:从单体到 Service Mesh》
java·面试·架构