原创

设计模式之建造者模式

作者:cndz 围观群众:593 更新于 标签:设计模式建造者模式

建造者模式是一种创建型设计模式,它允许你创建复杂对象。与工厂模式不同的是,建造者模式着重于将复杂对象的构建过程分解为多个简单但独立的步骤,并且可以按照不同的方式进行组合构建,从而使得同样的构建过程可以生成不同的表示。

本文将详细介绍建造者模式的概念、优缺点和应用场景,并通过一个实例来帮助读者更好地理解建造者模式的使用方法。

概念

建造者模式将一个复杂对象的构建过程(包括其各部件的构建)与其表示分离开来,使得同样的构建过程可以创建不同的表示。它将对象的构建过程封装在一个Builder接口中,并提供一个Director类来控制构建过程,从而实现对象的构建和表示分离。

优缺点

优点:

  1. 可以将对象构造过程和表示分离,使得同样的构造过程可以创建不同的表示形式。
  2. 可以方便地扩展和修改产品的构造过程,而不需要修改已有的代码。
  3. 客户端不需要知道具体的产品类或者构造细节,只需要知道Builder接口和Director类即可。
  4. 可以使用相同的构造过程来创建不同的产品,从而提高代码的复用性。

缺点:

  1. 建造者模式需要定义多个具体构造者类,增加了系统的复杂度。
  2. 当产品内部变化复杂时,可能会导致需要定义很多具体的Builder类来实现。

应用场景

建造者模式适用于以下场景:

  1. 需要生成的产品对象有复杂的内部结构,又因为某种原因需要将其构造过程分离开来。
  2. 需要生成的产品对象的属性相互依赖,需要按照特定顺序进行构造。
  3. 需要在不同情况下使用同一份代码来构造具有不同属性的对象。
  4. 在对象创建过程中需要进行一些额外的处理,如:日志记录、性能统计等。

实例

我们通过一个简单的实例来演示建造者模式的使用方法。假设我们正在开发一个游戏,需要创建一个角色(Role)类。角色对象包含以下属性:

  • 名称(name)
  • 性别(sex)
  • 职业(job)
  • 武器(weapon)
  • 衣服(clothes)

其中,职业、武器和衣服均是由多个部件组成的复杂对象。

首先,我们定义一个角色(Role)类。

public class Role {

    private String name;
    private String sex;
    private String job;
    private Weapon weapon;
    private Clothes clothes;

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

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    public void setClothes(Clothes clothes) {
        this.clothes = clothes;
    }

}

然后,我们定义职业、武器和衣服的部件类。

public class Profession {

    private String name;

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

}

public class Weapon {

    private String name;

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

}

public class Clothes {

    private String name;

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

}

然后,我们定义Builder接口,包含创建角色名称、性别、职业、武器和衣服的方法。

public interface RoleBuilder {

    void buildName(String name);

    void buildSex(String sex);

    void buildProfession(String professionName);

    void buildWeapons(List<String> weaponNames);

    void buildClothes(List<String> clothesNames);

    Role getResult();

}

接下来,我们实现具体的Builder类,分别用于构建不同种类的角色。

public class WarriorBuilder implements RoleBuilder {

    private Role role = new Role();

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

    @Override
    public void buildSex(String sex) {
        role.setSex(sex);
    }

    @Override
    public void buildProfession(String professionName) {
        Profession profession = new Profession();
        profession.setName(professionName);
        role.setJob(profession);
    }

    @Override
    public void buildWeapons(List<String> weaponNames) {
        List<Weapon> weapons = new ArrayList<>();
        for (String weaponName : weaponNames) {
            Weapon weapon = new Weapon();
            weapon.setName(weaponName);
            weapons.add(weapon);
        }
        role.setWeapons(weapons);
    }

    @Override
    public void buildClothes(List<String> clothesNames) {
        List<Clothes> clothes = new ArrayList<>();
        for (String clothesName : clothesNames) {
            Clothes cloth = new Clothes();
            cloth.setName(clothesName);
            clothes.add(cloth);
        }
        role.setClothes(clothes);
    }

    @Override
    public Role getResult() {
        return role;
    }
}

public class MageBuilder implements RoleBuilder {

    private Role role = new Role();

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

    @Override
    public void buildSex(String sex) {
        role.setSex(sex);
    }

    @Override
    public void buildProfession(String professionName) {
        Profession profession = new Profession();
        profession.setName(professionName);
        role.setJob(profession);
    }

    @Override
    public void buildWeapons(List<String> weaponNames) {
        List<Weapon> weapons = new ArrayList<>();
        for (String weaponName : weaponNames) {
            Weapon weapon = new Weapon();
            weapon.setName(weaponName);
            weapons.add(weapon);
        }
        role.setWeapons(weapons);
    }

    @Override
    public void buildClothes(List<String> clothesNames) {
        List<Clothes> clothes = new ArrayList<>();
        for (String clothesName : clothesNames) {
            Clothes cloth = new Clothes();
            cloth.setName(clothesName);
            clothes.add(cloth);
        }
        role.setClothes(clothes);
    }

    @Override
    public Role getResult() {
        return role;
    }
}

最后,我们定义Director类来控制构建过程。

public class Director {

    public Role construct(RoleBuilder builder) {
        builder.buildName("Tom");
        builder.buildSex("Male");
        builder.buildProfession("Warrior");
        List<String> weapons = new ArrayList<>();
        weapons.add("Sword");
        builder.buildWeapons(weapons);
        List<String> clothes = new ArrayList<>();
        clothes.add("Armor");
        builder.buildClothes(clothes);
        return builder.getResult();
    }

}

现在,我们可以使用Builder模式来创建不同的角色。

public class Client {

    public static void main(String[] args) {
        Director director = new Director();

        RoleBuilder warriorBuilder = new WarriorBuilder();
        Role warrior = director.construct(warriorBuilder);
        System.out.println(warrior);

        RoleBuilder mageBuilder = new MageBuilder();
        Role mage = director.construct(mageBuilder);
        System.out.println(mage);
    }

}

输出结果如下:

Role{name='Tom', sex='Male', job=Profession{name='Warrior'}, weapon=[Weapon{name='Sword'}], clothes=[Clothes{name='Armor'}]}
Role{name='Tom', sex='Male', job=Profession{name='Mage'}, weapon=[Weapon{name='Wand'}], clothes=[Clothes{name='Robe'}]}

可以看到,使用Builder模式创建了两个不同职业的角色对象,它们的属性值都是通过Director类控制构建过程而生成的。同时,由于Builder模式将构建过程和表示分离开来,因此我们可以方便地扩展和修改构造过程,而不需要修改已有的代码。

总之,Builder模式是一种非常实用的设计模式,在需要创建复杂对象时可以发挥很好的作用。

总结

通过以上代码实现,我们可以总结出Builder模式的特点:

  1. 将对象的构建过程和表示分离开来,使得同样的构建过程可以创建不同的表示。
  2. 隐藏对象的创建细节,使得客户端无需关心对象的创建过程。
  3. 便于扩展和修改构造过程,而不需要修改已有的代码。

在实际应用中,Builder模式通常用于创建复杂的对象,例如游戏角色、电子邮件等。因为这些对象包含大量的属性,并且这些属性之间存在着一定的约束关系,如果使用传统的构造函数进行创建,会导致构造函数参数列表过长或者过于复杂,难以维护和扩展。而使用Builder模式则可以将构建过程和表示分离开来,使得构造函数参数列表变得简洁明了,同时也方便了后期的扩展和维护。