Java设计模式:建造者模式的介绍及举例说明

199 阅读4分钟

建造者模式概念

建造者模式的意思是通过一个或多个建造者,将各种的零件组合成一个完整的产品。并且一个完整的产品可能需要多个零件组成,并且有些零件不可或缺,零件(属性)之间可能相互依赖。拿汉堡加工来举例,制作一个汉堡,需要面包、生菜、肉类、酱汁,假如没有面包就没法制作汉堡,如果没有肉类,制作出来的东西也不能叫做汉堡,并且制作汉堡的过程也需要一定的顺序,比如要先放面包,再放生菜和肉,最后才淋上酱汁。

建造者模式通常包含以下几个角色

  • 抽象构建者: 构建者的抽象接口,定义了构建产品的抽象方法
  • 具体构建者: 构建者抽象的具体实现,实现了构建产品的方法
  • 构建者的调度者: 用来调度构建者完成产品的构建
  • 产品: 要构建的具体产品

代码示例及说明

创建一个抽象构建者,包含一个构建汉堡的抽象方法

/**
 * 食品构建者抽象类
 */
public interface FootBuilder {
    HamBurg buildHamburg();
}

创建两个具体构建者,实现抽象构建者

/**
 * 1、普通汉堡构建者
 */
public class HamburgBuilder implements FootBuilder{
    //整个汉堡
    @Override
    public HamBurg buildHamburg(){
        HamBurg hamBurg = new HamBurg();
        hamBurg.setBread().setLeaf().setMeat().setSauce().setBrand("普通");
        return hamBurg;
    }
}
/**
 * 2、肯德基汉堡构建者
 */
public class KFCHamburgBuilder implements FootBuilder{
    //整个汉堡
    @Override
    public HamBurg buildHamburg(){
        HamBurg hamBurg = new HamBurg();
        hamBurg.setBread().setLeaf().setMeat().setSauce().setBrand("肯德基");
        return hamBurg;
    }
}

hamBurg.setBread().setLeaf().setMeat().setSauce().setBrand执行链表示产品构建过程,执行了放面包、加生菜、加肉片、加酱汁,最终完成汉堡构建的过程。
创建普通汉堡产品类

/**
 * 汉堡包
 */
public class HamBurg {
    //面包
    private boolean bread;
    //肉
    private boolean meat;
    //生菜
    private boolean leaf;
    //酱汁
    private boolean sauce;
    //品牌
    private String brand;


    public HamBurg setBread() {
        this.bread = true;
        return this;
    }

    public HamBurg setMeat() {
        if(!this.bread){
            throw new RuntimeException("要先放面包片");
        }
        this.meat = true;
        return this;
    }

    public HamBurg setLeaf() {
        if(!this.bread){
            throw new RuntimeException("要先放面包片");
        }
        this.leaf = true;
        return this;
    }

    public HamBurg setSauce() {
        if(!this.leaf||!meat){
            throw new RuntimeException("请先放生菜或肉片后,在加酱汁");
        }
        this.sauce = true;
        return this;
    }

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

    @Override
    public String toString() {
        return this.brand+"汉堡制作完成";
    }
}

上面的代码定义了产品所包含的属性,就是用这些属性去模拟产品构建的过程。

创建肯德基汉堡产品类

/**
 * 肯德基汉堡包
 */
public class KFCHamBurg {
    //面包
    private boolean bread;
    //肉
    private boolean meat;
    //生菜
    private boolean leaf;
    //酱汁
    private boolean sauce;
    //品牌
    private String brand;


    public KFCHamBurg setBread() {
        this.bread = true;
        return this;
    }

    public KFCHamBurg setMeat() {
        if(!this.bread){
            throw new RuntimeException("要先放面包片");
        }
        this.meat = true;
        return this;
    }

    public KFCHamBurg setLeaf() {
        if(!this.bread){
            throw new RuntimeException("要先放面包片");
        }
        this.leaf = true;
        return this;
    }

    public KFCHamBurg setSauce() {
        if(!this.leaf||!meat){
            throw new RuntimeException("请先放生菜或肉片后,在加酱汁");
        }
        this.sauce = true;
        return this;
    }

    public void setBread(String brand) {
        this.bread = bread;
    }

    @Override
    public String toString() {
        return this.brand+"汉堡制作完成";
    }
}

上面的代码定义了肯德基汉堡所包含的属性,就是按一定顺序调用这些属性的修改方法去模拟产品构建的过程

提示
如果一个产品是更加复杂的,并且无法使用一个类来表示,那么就应该考虑将产品的属性定义为可以包含更多属性的对象类型

创建构建者的调度者

public class HamBurgDirector {
    private FootBuilder builder;

    public HamBurgDirector(FootBuilder builder){
        this.builder = builder;
    }
    public HamBurg getHamBurg(){
        return builder.buildHamburg();
    }
}

这个类的作用是调用具体构建者构建产品的方法,直到完成产品的构建。

提示
对于更加复杂的产品,一个产品对象往往需要组合多个对象属性来构建产品,这个时候调度者类就会显得特别重要,可能需要在调度者中,调度构建者的多个方法完成产品的构建工作

创建测试类测试

public class test {
    public static void main(String[] args) {
        //构建普通汉堡
        FootBuilder builder = new HamburgBuilder();
        HamBurgDirector director = new HamBurgDirector(builder);
        HamBurg hamBurg = director.getHamBurg();
        System.out.println(hamBurg);
        //构建肯德基汉堡
        builder = new KFCHamburgBuilder();
        director = new HamBurgDirector(builder);
        HamBurg kfcHamBurg = director.getHamBurg();
        System.out.println(kfcHamBurg);
    }
}

输出结果: image.png

上面的代码只是构建者模式的一个简单示例,主要想表达的意思是,当需要生产的产品是由多个产品组合而成时,往往需要一个构建者去构建对象的内部零件,这个零件可以理解为一个属性或是一个对象。调度者可以理解为是一个指挥构建者构建产品的角色,调度者拿到不同构建者构建的产品,还可以再将这些产品进行组合形成一个类似于套餐组合的东西。

总结

总之通过建造者模式,可以更好的将产品的制作步骤拆分出来,分离出具体的制作过程之后, 就可以更好的控制每一步的构建细节,这种松散的设计有利于分工合作,使程序更灵活, 并且提高了代码的复用性。