Android初探建造者模式

[TOC]

一、建造者模式

定义:

构建者模式(Builder Pattern)是一种创建型设计模式,旨在通过提供一种灵活的方式来构建复杂对象。该模式将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

具体来说,构建者模式使用一个独立的构建器(Builder)类来封装对象的构建过程。构建器类提供一系列方法来设置对象的属性,并最终返回构建好的对象。这种方式可以避免使用多个构造函数或过多的参数,使得对象的构建过程更加直观和易于扩展。

生活中的例子:

假设你要建造一座房子,房子有多个组成部分,例如墙壁、门、窗户等。使用构建者模式可以将建造房子的过程分解为以下步骤:

创建一个房子构建器类(HouseBuilder),该类负责构建房子对象。
在房子构建器类中定义一系列方法,例如 buildWalls()、buildDoors()、buildWindows() 等,用于设置房子的各个组成部分。
客户端代码创建一个房子构建器对象,并使用该对象调用相应的方法来设置房子的属性,例如设置墙壁类型、设置门的数量、设置窗户的尺寸等。
最后,房子构建器对象调用 build() 方法返回构建好的房子对象。
使用构建者模式,在不同的场景下可以定制化构建不同类型的房子,而且可以灵活地添加或修改构建过程中的步骤。

总结一下,构建者模式通过将复杂对象的构建过程与其表示分离,提供了一种灵活且可扩展的方式来构建对象。

二、建造者模式作用

建造者模式是一种创建型设计模式,主要用于构建复杂对象。它的作用是将对象的创建过程与表示分离,以便可以使用相同的构建过程来创建不同的表示。

具体来说,建造者模式的作用如下:

封装复杂对象的创建过程:建造者模式将复杂对象的构建过程封装在具体建造者中,客户端无需知道对象的具体创建细节,只需要通过指挥者或者具体建造者来完成对象的构建。

提供灵活的构建流程:建造者模式允许客户端通过不同的组合方式来构建对象,从而灵活地生成不同的表示。客户端可以根据需求自由选择具体建造者,并按照需要调用建造者的方法来设置对象的属性。

支持逐步构建复杂对象:通过建造者模式,可以逐步构建复杂对象,每一步都可以通过建造者的方法来设置对象的属性,最终调用建造者的方法返回构建好的对象。这种逐步构建的方式对于某些复杂对象的构建非常有帮助。

避免构造方法参数过多:对于具有大量属性的对象,如果使用构造方法来创建对象,会出现参数过多、参数顺序困扰等问题。而建造者模式通过链式调用设置属性,避免了构造方法参数过多的问题,使得代码更加清晰易读。

支持对象属性的变化:如果一个对象的属性有较高的变动性,使用建造者模式可以很方便地修改具体建造者的实现,而无需修改客户端的代码。这样可以降低耦合度,提高系统的可维护性和可扩展性。

总而言之,建造者模式将复杂对象的创建过程封装起来,提供灵活的构建流程,以及逐步构建复杂对象的能力,同时避免了构造方法参数过多的问题,支持对象属性的变化。它能够帮助我们更好地组织和管理复杂对象的创建,提高代码的可读性、可维护性和可扩展性。

三、建造者模式案例

下面是我自己本人在csdn上学习他人博客写的一个小案例,如有错误欢迎指出,自己也是第一次学习建造者模式,还存在很多很多不懂之处。

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
package com.example.constraintlayoutlearning;

/**
* @Author Crwei
* date 2023/9/18 19:48
*/

public class TestPerson {
public String mPersonName;
private int mPersonAge;
private int mSex;
private String mCardNumber;

public String getmPersonName() {
return mPersonName;
}

public int getmPersonAge() {
return mPersonAge;
}

public TestPerson(TestPerson.Builder builder){
this.mCardNumber = builder.mCardNumber;
this.mSex = builder.mSex;
this.mPersonAge = builder.mPersonAge;
this.mPersonName = builder.mPersonName;
if(this.mPersonAge>100){
throw new IllegalArgumentException("年龄不能超过100");
}
}

public static final class Builder {
private String mPersonName;
private int mPersonAge;
private int mSex;
private String mCardNumber;

public Builder(){}

public TestPerson build(){
return new TestPerson(this);
}

public TestPerson.Builder addPersonName(String mPersonName) {
this.mPersonName = mPersonName;
return this;
}
public TestPerson.Builder addPersonAge(int mPersonAge) {
this.mPersonAge = mPersonAge;
return this;
}
public TestPerson.Builder addSex(int mSex) {
this.mSex = mSex;
return this;
}
public TestPerson.Builder addCardNumber(String mCardNumber) {
this.mCardNumber = mCardNumber;
return this;
}
}
}

这里对TestPerson类使用了构建者模式,该类的建立参考来源 。

从上面可以看到,除了mPersonName是用public修饰的,其余都是private,为什么要用public以及对这个属性设置了两个ge方法,这和我使用Databing有关,这里我们等会说,一般都是使用private(而且还可以加final修饰)。

定义完基本的属性以后,我们在下面定义了一个用final实现的抽象类Builder,这样做的目的是为了避免在子类中修改build方法,以保持整个类的稳定性和一致性,同时也可以提高性能,因为final修饰会在编译的时候被内联优化。在Builder中我们又定义了和TestPerson相同的属性,这些属性的修饰符都是private。然后我们提供了大量的方法来set Builder中的属性值,并且将其赋值给调用者。

使用方法:

    try{
        person = new TestPerson.Builder()
                .addPersonName("张三")
                .addSex(1)
                .addPersonAge(122)
                .build();
    }catch (IllegalArgumentException e){
        System.out.println(e.getMessage());
    }

可能有人问,这里为什么要用try-catch,注意看上面代码的这一部分

1
2
3
4
5
6
7
8
9
public TestPerson(TestPerson.Builder builder){
this.mCardNumber = builder.mCardNumber;
this.mSex = builder.mSex;
this.mPersonAge = builder.mPersonAge;
this.mPersonName = builder.mPersonName;
if(this.mPersonAge>100){
throw new IllegalArgumentException("年龄不能超过100");
}
}

我们对这个属性做了一个限制,因为我们实际使用的时候,肯定会有一些属性有所限制,我们可以直接在这里就对限制做了处理,然后在Builder的时候使用try-catch捕获异常,可以更方便的知道数据是否存在问题。

上面的代码虽然使用了建造者模式,但是还是可以优化的,有一个插件叫Lombok,使用该插件可以减少TestPerson的大量代码,我还没有用过,我就不介绍了,有兴趣的朋友可以自行研究。

四、建造者模式的使用场景

创建复杂对象:当需要创建一个带有多个属性并且初始化过程较为复杂的对象时,可以使用建造者模式。通过逐步设置对象的属性,并在最后一步构建对象,能够简化对象的创建过程。

需要灵活组合对象属性:建造者模式能够根据需要选择性地设置对象的属性。可以按照不同的需求组合不同的属性,而无需创建多个独立的构造函数或使用大量的可选参数。

避免重叠构造器问题:当一个类的属性较多,存在多种组合方式时,使用传统的多个构造函数容易造成构造器重叠问题。而建造者模式可以通过链式调用的方式避免这个问题,并使代码更加清晰易读。

支持不可变对象构建:建造者模式可以创建不可变对象,即对象一旦创建就不能再修改其属性值。通过在Builder类中将对象的属性设置为final,并在build方法中创建不可变对象,可以确保对象的属性值在创建后不会被修改。

便于扩展:如果需要为已有的对象添加新的属性,或者需要创建该类的子类,使用建造者模式能够方便地进行扩展和修改。

总的来说,建造者模式适用于需要创建复杂对象,并且需要对对象属性进行灵活组合和控制的场景。它能够提高代码的可读性、可维护性和可扩展性。

像我们使用的Okhttp以及一些dialog里面大部分都是使用的建造者模式的,使用建造者模式可以让使用者更方便灵活的使用他们。

五、一些思考

我在学习建造者模式的时候是和databing一起使用的,在使用的过程中我发现,当TestPerson的属性都是private的时候,我在xml中这样使用是不可以的,无法获取到对象的值,当我将该属性的值的修饰符从private改成public的时候就可以获取到了,我很不解。

只有把mPersonName的修饰符改成public才行,如果有更好的方案实现或者其他方法评论区交流,目前本人刚学,刚刚入门建造者模式。

我以为是private在建造者模式里面无法通过get拿到值,但是我在activity or fragment中又可以拿到值。

这里又可以拿到另外一个private修饰的属性的值,我不理解。

后面还会进行更新本文,今天是对建造者模式的初步了解,还有很多不会的地方,学生所做,如有写错,敬请批评指正。


Android初探建造者模式
https://crwei996.github.io/2023/09/19/Android初探建造者模式/
Author
Crwei996
Posted on
September 19, 2023
Licensed under