Post

建造者模式

建造者模式

建造者模式

题目链接

建造者模式-自行车加工

什么是建造者模式

建造者模式(也被成为生成器模式),是一种创建型设计模式,软件开发过程中有的时候需要创建很复杂的对象,而建造者模式的主要思想是将对象的构建过程分为多个步骤,并为每个步骤定义一个抽象的接口。具体的构建过程由实现了这些接口的具体建造者类来完成。同时有一个指导者类负责协调建造者的工作,按照一定的顺序或逻辑来执行构建步骤,最终生成产品。

举个例子,假如我们要创建一个计算机对象,计算机由很多组件组成,例如 CPU、内存、硬盘、显卡等。每个组件可能有不同的型号、配置和制造,这个时候计算机就可以被视为一个复杂对象,构建过程相对复杂,而我们使用建造者模式将计算机的构建过程封装在一个具体的建造者类中,而指导者类则负责指导构建的步骤和顺序。每个具体的建造者类可以负责构建不同型号或配置的计算机,客户端代码可以通过选择不同的建造者来创建不同类型的计算机,这样就可以根据需要构建不同表示的复杂对象,更加灵活。

基本结构

建造者模式有下面几个关键角色:

  • 产品Product:被构建的复杂对象, 包含多个组成部分。
  • 抽象建造者Builder: 定义构建产品各个部分的抽象接口和一个返回复杂产品的方法getResult
  • 具体建造者Concrete Builder:实现抽象建造者接口,构建产品的各个组成部分,并提供一个方法返回最终的产品。
  • 指导者Director:调用具体建造者的方法,按照一定的顺序或逻辑来构建产品。

在客户端中,通过指导者来构建产品,而并不和具体建造者进行直接的交互。

image-20240104144826759

简易实现

建造者模式的实现步骤通常包括以下几个阶段

  1. 定义产品类:产品类应该包含多个组成部分,这些部分的属性和方法构成了产品的接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 产品类
class Product {
    private String part1;
    private String part2;

    public void setPart1(String part1) {
        this.part1 = part1;
    }

    public void setPart2(String part2) {
        this.part2 = part2;
    }

    // 其他属性和方法
}

  1. 定义抽象建造者接口:创建一个接口,包含构建产品各个部分的抽象方法。这些方法通常用于设置产品的各个属性。
1
2
3
4
5
6
7
8
// 抽象建造者接口
interface Builder {
    void buildPart1(String part1);
    void buildPart2(String part2);
    Product getResult();
}

  1. 创建具体建造者:实现抽象建造者接口,构建具体的产品。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 具体建造者类
class ConcreteBuilder implements Builder {
    private Product product = new Product();

    @Override
    public void buildPart1(String part1) {
        product.setPart1(part1);
    }

    @Override
    public void buildPart2(String part2) {
        product.setPart2(part2);
    }

    @Override
    public Product getResult() {
        return product;
    }
}

  1. 定义Director类: 指导者类来控制构建产品的顺序和步骤。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 指导者类
class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }
	// 调用方法构建产品
    public void construct() {
        builder.buildPart1("Part1");
        builder.buildPart2("Part2");
    }
}

  1. 客户端使用建造者模式:在客户端中创建【具体建造者对象】和【指导者对象】,通过指导者来构建产品。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 客户端代码
public class Main{
    public static void main(String[] args) {
        // 创建具体建造者
        Builder builder = new ConcreteBuilder();

        // 创建指导者
        Director director = new Director(builder);

        // 指导者构建产品
        director.construct();

        // 获取构建好的产品
        Product product = builder.getResult();
        
        // 输出产品信息
        System.out.println(product);
    }
}

使用场景

使用建造者模式有下面几处优点:

  • 使用建造者模式可以将一个复杂对象的构建与其表示分离,通过将构建复杂对象的过程抽象出来,可以使客户端代码与具体的构建过程解耦

  • 同样的构建过程可以创建不同的表示,可以有多个具体的建造者(相互独立),可以更加灵活地创建不同组合的对象。

对应的,建造者模式适用于复杂对象的创建,当对象构建过程相对复杂时可以考虑使用建造者模式,但是当产品的构建过程发生变化时,可能需要同时修改指导类和建造者类,这就使得重构变得相对困难。

建造者模式在现有的工具和库中也有着广泛的应用,比如JUnit 中的测试构建器TestBuilder就采用了建造者模式,用于构建测试对象。

本题代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import java.util.Scanner;

// 自行车产品
class Bike {
    private String frame;
    private String tires;

    public void setFrame(String frame) {
        this.frame = frame;
    }

    public void setTires(String tires) {
        this.tires = tires;
    }

    @Override
    public String toString() {
        return frame + " " + tires;
    }
}

// 自行车建造者接口
interface BikeBuilder {
    void buildFrame();
    void buildTires();
    Bike getResult();
}

// 山地自行车建造者
class MountainBikeBuilder implements BikeBuilder {
    private Bike bike;

    public MountainBikeBuilder() {
        this.bike = new Bike();
    }

    @Override
    public void buildFrame() {
        bike.setFrame("Aluminum Frame");
    }

    @Override
    public void buildTires() {
        bike.setTires("Knobby Tires");
    }

    @Override
    public Bike getResult() {
        return bike;
    }
}

// 公路自行车建造者
class RoadBikeBuilder implements BikeBuilder {
    private Bike bike;

    public RoadBikeBuilder() {
        this.bike = new Bike();
    }

    @Override
    public void buildFrame() {
        bike.setFrame("Carbon Frame");
    }

    @Override
    public void buildTires() {
        bike.setTires("Slim Tires");
    }

    @Override
    public Bike getResult() {
        return bike;
    }
}

// 自行车Director,负责构建自行车
class BikeDirector {
    public Bike construct(BikeBuilder builder) {
        builder.buildFrame();
        builder.buildTires();
        return builder.getResult();
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int N = scanner.nextInt();  // 订单数量
        scanner.nextLine();

        BikeDirector director = new BikeDirector();

        for (int i = 0; i < N; i++) {
            String bikeType = scanner.nextLine();

            BikeBuilder builder;
            // 根据输入类别,创建不同类型的具体建造者
            if (bikeType.equals("mountain")) {
                builder = new MountainBikeBuilder();
            } else {
                builder = new RoadBikeBuilder();
            }
			// Director负责指导生产产品
            Bike bike = director.construct(builder);
            System.out.println(bike);
        }
    }
}

其他语言代码

Cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <iostream>
#include <string>
 
// 自行车产品
class Bike {
public:
    std::string frame;
    std::string tires;
 
    void setFrame(const std::string& frame) {
        this->frame = frame;
    }
 
    void setTires(const std::string& tires) {
        this->tires = tires;
    }
 
    friend std::ostream& operator<<(std::ostream& os, const Bike& bike) {
        os << bike.frame << " " << bike.tires;
        return os;
    }
};
 
// 自行车建造者接口
class BikeBuilder {
public:
    virtual void buildFrame() = 0;
    virtual void buildTires() = 0;
    virtual Bike getResult() = 0;
};
 
// 山地自行车建造者
class MountainBikeBuilder : public BikeBuilder {
private:
    Bike bike;
 
public:
    void buildFrame() override {
        bike.setFrame("Aluminum Frame");
    }
 
    void buildTires() override {
        bike.setTires("Knobby Tires");
    }
 
    Bike getResult() override {
        return bike;
    }
};
 
// 公路自行车建造者
class RoadBikeBuilder : public BikeBuilder {
private:
    Bike bike;
 
public:
    void buildFrame() override {
        bike.setFrame("Carbon Frame");
    }
 
    void buildTires() override {
        bike.setTires("Slim Tires");
    }
 
    Bike getResult() override {
        return bike;
    }
};
 
// 自行车Director,负责构建自行车
class BikeDirector {
public:
    Bike construct(BikeBuilder& builder) {
        builder.buildFrame();
        builder.buildTires();
        return builder.getResult();
    }
};
 
int main() {
    int N;
    std::cin >> N;  // 订单数量
 
    BikeDirector director;
 
    for (int i = 0; i < N; i++) {
        std::string bikeType;
        std::cin >> bikeType;
 
        BikeBuilder* builder;
 
        // 根据输入类别,创建不同类型的具体建造者
        if (bikeType == "mountain") {
            builder = new MountainBikeBuilder();
        } else {
            builder = new RoadBikeBuilder();
        }
 
        // Director负责指导生产产品
        Bike bike = director.construct(*builder);
        std::cout << bike << std::endl;
 
        // 释放动态分配的对象
        delete builder;
    }
 
    return 0;
}

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 自行车产品
class Bike:
    def __init__(self):
        self.frame = None
        self.tires = None
 
    def set_frame(self, frame):
        self.frame = frame
 
    def set_tires(self, tires):
        self.tires = tires
 
    def __str__(self):
        return f"{self.frame} {self.tires}"
 
# 自行车建造者接口
class BikeBuilder:
    def build_frame(self):
        pass
 
    def build_tires(self):
        pass
 
    def get_result(self):
        pass
 
# 山地自行车建造者
class MountainBikeBuilder(BikeBuilder):
    def __init__(self):
        self.bike = Bike()
 
    def build_frame(self):
        self.bike.set_frame("Aluminum Frame")
 
    def build_tires(self):
        self.bike.set_tires("Knobby Tires")
 
    def get_result(self):
        return self.bike
 
# 公路自行车建造者
class RoadBikeBuilder(BikeBuilder):
    def __init__(self):
        self.bike = Bike()
 
    def build_frame(self):
        self.bike.set_frame("Carbon Frame")
 
    def build_tires(self):
        self.bike.set_tires("Slim Tires")
 
    def get_result(self):
        return self.bike
 
# 自行车Director,负责构建自行车
class BikeDirector:
    def construct(self, builder):
        builder.build_frame()
        builder.build_tires()
        return builder.get_result()
 
def main():
    N = int(input())  # 订单数量
 
    director = BikeDirector()
 
    for _ in range(N):
        bike_type = input()
 
        # 根据输入类别,创建不同类型的具体建造者
        if bike_type == "mountain":
            builder = MountainBikeBuilder()
        else:
            builder = RoadBikeBuilder()
 
        # Director负责指导生产产品
        bike = director.construct(builder)
        print(bike)
 
if __name__ == "__main__":
    main()

Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main

import "fmt"

// 自行车产品
type Bike struct {
	frame string
	tires string
}

func (b *Bike) setFrame(frame string) {
	b.frame = frame
}

func (b *Bike) setTires(tires string) {
	b.tires = tires
}

func (b *Bike) String() string {
	return b.frame + " " + b.tires
}

// 自行车建造者接口
type BikeBuilder interface {
	buildFrame()
	buildTires()
	getResult() *Bike
}

// 山地自行车建造者
type MountainBikeBuilder struct {
	bike *Bike
}

func NewMountainBikeBuilder() *MountainBikeBuilder {
	return &MountainBikeBuilder{
		bike: &Bike{},
	}
}

func (mbb *MountainBikeBuilder) buildFrame() {
	mbb.bike.setFrame("Aluminum Frame")
}

func (mbb *MountainBikeBuilder) buildTires() {
	mbb.bike.setTires("Knobby Tires")
}

func (mbb *MountainBikeBuilder) getResult() *Bike {
	return mbb.bike
}

// 公路自行车建造者
type RoadBikeBuilder struct {
	bike *Bike
}

func NewRoadBikeBuilder() *RoadBikeBuilder {
	return &RoadBikeBuilder{
		bike: &Bike{},
	}
}

func (rbb *RoadBikeBuilder) buildFrame() {
	rbb.bike.setFrame("Carbon Frame")
}

func (rbb *RoadBikeBuilder) buildTires() {
	rbb.bike.setTires("Slim Tires")
}

func (rbb *RoadBikeBuilder) getResult() *Bike {
	return rbb.bike
}

// 自行车Director,负责构建自行车
type BikeDirector struct{}

func (bd *BikeDirector) construct(builder BikeBuilder) *Bike {
	builder.buildFrame()
	builder.buildTires()
	return builder.getResult()
}

func main() {
	var N int
	fmt.Scan(&N) // 订单数量

	director := &BikeDirector{}

	for i := 0; i < N; i++ {
		var bikeType string
		fmt.Scan(&bikeType)

		var builder BikeBuilder
		// 根据输入类别,创建不同类型的具体建造者
		if bikeType == "mountain" {
			builder = NewMountainBikeBuilder()
		} else {
			builder = NewRoadBikeBuilder()
		}
		// Director负责指导生产产品
		bike := director.construct(builder)
		fmt.Println(bike)
	}
}

ref kama-Design-pattern

This post is licensed under CC BY 4.0 by the author.