java & 设计模式 & 建造者模式

176 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

什么是建造者模式

  • 建造者模式又叫生成器迷失,是一种对象构建模式,它可以将复杂对象的建造过程抽象出来,使整个抽象过程的不同实现方法可以构造出不同表现的对象。
  • 建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建他们,也就是用户不用知道具体的构建细节。

建造者模式里面的四个角色

  • 产品角色:具体的产品对象
  • 抽象建造者:创建一个Product对象的各个部件指定的接口/抽象类。
  • 具体建造者:实现接口,构建和装配各个部件
  • 指挥者:构建一个使用 抽象建造者的对象,主要用于创建一个复杂的对象。隔离客户与对象的生产过程,负责控制产品对象

下面我们使用一个场景来使用 建造者模式

盖房子 :打地基,砌墙,封顶(普通房子,高楼,别墅等)
传统方式:应该先创建一抽象类 或者 接口 提取公共方法 再使用不同的实现类去实现每个类型的房子 准备抽象类

public abstract class AbstraHouse {
   public abstract void buildbasic();
   public abstract void buildWalls();
   public abstract void roofed();

   public  void build(){
       buildbasic();
       buildWalls();
       roofed();
   }
}

创建普通房子继承

public class OrdinaryHouses extends AbstraHouse {

    @Override
    public void buildbasic() {
        System.out.println("普通房子 打地基5米");
    }

    @Override
    public void buildWalls() {
        System.out.println("普通房子 砌墙");
    }

    @Override
    public void roofed() {
        System.out.println("普通房子 封顶");
    }
}

调用创建

public class Client {
    public static void main(String[] args) {
        OrdinaryHouses tbShopping = new OrdinaryHouses();
        tbShopping.build();
    }
}

类图

image.png 这种方式比较好理解,且简单操作,结构简单没有设计缓存层对象,不利于程序的扩展和维护。这种设计方案,把产品和创建产品 封装在了一起,耦合性增强了。产品不应该和创建过程封装在一起

下面我们来看看建造者模式

类图

image.png 产品角色:House

@Data
public class House {
    private String basic;
    private String type;
}

抽象建造者:

public abstract class HouseBuilder {
    protected House house= new House();


    public abstract void buildbasic();
    public abstract void buildWalls();
    public abstract void roofed();
    public abstract String basic();
    public abstract String type();
    //将创建的House返回
    public House getHouse() {
        house.setType(type());
        house.setBasic(basic());
        return house;
    }
}

具体建造者:

public class OrdinaryHouses extends HouseBuilder{
    @Override
    public void buildbasic() {
        System.out.println("普通房子 打地基5米");
    }

    @Override
    public void buildWalls() {
        System.out.println("普通房子 砌墙");
    }

    @Override
    public void roofed() {
        System.out.println("普通房子 封顶");
    }

    @Override
    public String basic() {
        return "5 m";
    }


    @Override
    public String type() {
        return "普通房子";
    }
}
public class HighHouses extends HouseBuilder{
    @Override
    public void buildbasic() {
        System.out.println("高楼 打地基20米");
    }

    @Override
    public void buildWalls() {
        System.out.println("高楼 砌墙");
    }

    @Override
    public void roofed() {
        System.out.println("高楼 封顶");
    }

    @Override
    public String basic() {
        return "20 m";
    }


    @Override
    public String type() {
        return "高楼";
    }
}

指挥者:

public class HouseDirector {

    HouseBuilder houseBuilder = null;
    //通过set方法传入 抽象建造者的继承者 即就是具体建造者 当然这里也可以用构造器的方式传入 具体建造者
    public void setHouseBuilder(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }
    //如何创建房子以及流程,指挥者来分配
    public House createHouse(){
        houseBuilder.buildbasic();
        houseBuilder.buildWalls();
        houseBuilder.roofed();
        House house = houseBuilder.getHouse();
        return house;
    }
}

最后是调用测试:

public class Client {
    public static void main(String[] args) {
        OrdinaryHouses ordinaryHouses =new OrdinaryHouses();
        HouseDirector houseDirector=new HouseDirector();
        //创建普通房子
        houseDirector.setHouseBuilder(ordinaryHouses);
        House house = houseDirector.createHouse();
        System.out.println("house = " + house);
        HighHouses highHouses =new HighHouses();
        houseDirector.setHouseBuilder(highHouses);
        House house2 = houseDirector.createHouse();
        System.out.println("house2 = " + house2);

    }
}

输出结果:

普通房子 打地基5米
普通房子 砌墙
普通房子 封顶
house = House(basic=5 m, type=普通房子)
高楼 打地基20米
高楼 砌墙
高楼 封顶
house2 = House(basic=20 m, type=高楼)

建造模式总结

调用端不必知道产品内部是如何组成的细节,将产品本身与创建过程进行解耦,即同一个创建过程可以创建不同的传品对象。 每一个具体的创建者都是相对独立的,因此一个改动不会影响到其他具体的创建这个。可以更加精细的控制产品的控制过程。 指挥者类针对抽象建造者编程系统扩展更加方便 符合 开闭原则。如果产品之家的差异性很大,则不适合使用建造者模式。

实践是检验真理的唯一方法! 明天见🥰🥰🥰