一起来学设计模式之建造者模式

1,142 阅读8分钟

前言

目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~

本节给大家讲一下设计模式中的建造者模式,并结合实际业务场景给大家讲解如何使用~

本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~

建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,它可以将一个复杂对象的构建过程分解为多个简单的步骤,并将这些步骤分别实现,从而使得同样的构建过程可以创建不同的表示。建造者模式常用于构建一些需要经过多个步骤才能完成的复杂对象,例如汽车、电脑等。

建造者模式中,通常有四个角色:抽象建造者(Builder)、具体建造者(ConcreteBuilder)、产品(Product)和指挥者(Director)。其中,抽象建造者定义了创建产品的抽象方法和部件,具体建造者实现了这些抽象方法,并创建了一个具体产品,产品是由具体建造者构建的对象,指挥者则负责指导具体建造者进行构建,并且可以根据不同的需要指定不同的建造者进行构建。

假设我们要构建一个简单的人类,包括姓名、年龄、性别和职业等属性。我们可以先定义一个人类对象,它包含了所有的属性:

public class Person {
    private String name;
    private int age;
    private String gender;
    private String occupation;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public void setOccupation(String occupation) {
        this.occupation = occupation;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", occupation='" + occupation + '\'' +
                '}';
    }
}

接下来,我们定义一个抽象建造者接口,包含了创建人类对象的方法和设置属性的方法:

public interface PersonBuilder {
    void createPerson();
    void setName(String name);
    void setAge(int age);
    void setGender(String gender);
    void setOccupation(String occupation);
    Person getPerson();
}

然后,我们定义具体建造者类,实现了抽象建造者接口,具体实现了创建人类对象和设置属性的方法:

public class ConcretePersonBuilder implements PersonBuilder {
    private Person person;

    @Override
    public void createPerson() {
        person = new Person();
    }

    @Override
    public void setName(String name) {
        person.setName(name);
    }

    @Override
    public void setAge(int age) {
        person.setAge(age);
    }

    @Override
    public void setGender(String gender) {
        person.setGender(gender);
    }

    @Override
    public void setOccupation(String occupation) {
        person.setOccupation(occupation);
    }

    @Override
    public Person getPerson() {
        return person;
    }
}

最后,我们定义一个指挥者类,负责指导具体建造者进行构建:

public class PersonDirector {
    private PersonBuilder builder;

    public PersonDirector(PersonBuilder builder) {
        this.builder = builder;
    }

    public void constructPerson(String name, int age, String gender, String occupation) {
        builder.createPerson();
        builder.setName(name);
        builder.setAge(age);
        builder.setGender(gender);
        builder.setOccupation(occupation);
    }
}

接下来我们使用它:

public class BuilderTest {
    public static void main(String[] args) throws Exception {
        PersonBuilder builder = new ConcretePersonBuilder();
        PersonDirector director = new PersonDirector(builder);
        director.constructPerson("张三", 20, "男", "学生");
        Person person = builder.getPerson();
        System.out.println(person.toString());
       
    }
}

看下输出:

Person{name='张三', age=20, gender='男', occupation='学生'}

从上面的例子可以看出,建造者模式可以将一个复杂对象的构建过程分解为多个简单的步骤,并且可以根据不同的需要指定不同的具体建造者来构建不同的对象。同时,建造者模式还可以隐藏对象的创建和实现细节,使得调用者只需要知道如何构建一个对象,而不需要知道对象的具体实现过程,从而提高了系统的灵活性和可维护性。

最佳实践

现在,我们就结合实际业务给大家展示一下如何使用建造者模式,跟上节一样,依然举电商平台的例子。

假设有一个电商平台,用户可以在平台上购买商品,商品有多种属性,包括名称、描述、价格、库存、品牌、分类等等。我们可以使用建造者模式来实现商品对象的构建过程。

首先,定义一个商品类,包含多个属性:

@Data
public class Product {
    private String name;
    private String description;
    private BigDecimal price;
    private int stock;
    private String brand;
    private String category;

    public Product(String name, String description, BigDecimal price, int stock, String brand, String category) {
        this.name = name;
        this.description = description;
        this.price = price;
        this.stock = stock;
        this.brand = brand;
        this.category = category;
    }
}

然后,定义一个商品构造器接口,包含设置商品名称、描述、价格、库存、品牌、分类的方法:

public interface ProductBuilder {
    Product build();
    void setName(String name);
    void setDescription(String description);
    void setPrice(BigDecimal price);
    void setStock(int stock);
    void setBrand(String brand);
    void setCategory(String category);
}

接下来,定义一个具体商品构造器,实现商品构造器接口,实现每个属性的设置方法:

public class ConcreteProductBuilder implements ProductBuilder {
    private String name;
    private String description;
    private BigDecimal price;
    private int stock;
    private String brand;
    private String category;

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    @Override
    public void setStock(int stock) {
        this.stock = stock;
    }

    @Override
    public void setBrand(String brand) {
        this.brand = brand;
    }

    @Override
    public void setCategory(String category) {
        this.category = category;
    }

    @Override
    public Product build() {
        return new Product(name, description, price, stock, brand, category);
    }
}

最后,定义一个商品构造器指挥者,包含一个具体商品构造器对象,可以使用具体商品构造器对象来构建商品对象:

public class ProductDirector {
    private ProductBuilder builder;

    public ProductDirector(ProductBuilder builder) {
        this.builder = builder;
    }

    public Product constructProduct(String name, String description, BigDecimal price, int stock, String brand, String category) {
        builder.setName(name);
        builder.setDescription(description);
        builder.setPrice(price);
        builder.setStock(stock);
        builder.setBrand(brand);
        builder.setCategory(category);
        return builder.build();
    }
}

现在,我们可以使用建造者模式来构建商品对象:

public class BuilderTest {
    public static void main(String[] args) throws Exception {
        ProductBuilder builder = new ConcreteProductBuilder();
        ProductDirector director = new ProductDirector(builder);
        Product product = director.constructProduct("iPhone 13", "Apple手机", new BigDecimal("7999.00"), 100, "Apple", "手机");
        System.out.println(product);
        // Product(name=iPhone 13, description=Apple手机, price=7999.00, stock=100, brand=Apple, category=手机)
    }
}

结束语

设计模式其实并不难,大家在学习的时候一定要在理解的基础上去写代码,不要去背代码。下节给大家讲原型模式~

本着把自己知道的都告诉大家,如果本文对您有所帮助,点赞+关注鼓励一下呗~

相关文章

项目源码(源码已更新 欢迎star⭐️)

Kafka 专题学习

项目源码(源码已更新 欢迎star⭐️)

ElasticSearch 专题学习

项目源码(源码已更新 欢迎star⭐️)

往期并发编程内容推荐

推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)

博客(阅读体验较佳)

本文正在参加「金石计划」