乐趣区

关于设计模式:一文彻底搞懂设计模式之建造者模式Builder

文章已收录我的仓库:Java 学习笔记与收费书籍分享

设计用意

为了将简单对象的构建与它的示意拆散,使得对象能够通过不同的示意创立进去。

例如对一个迷宫可能有墙、房间和门,并且数量不计。迷宫可能仅由一堵墙形成,也可能由两堵墙形成,也可能由 2 个房间加一扇门形成 … 如果采纳重载的形式生产迷宫,代码量是难以计数的、无比宏大的。

针对一个对象领有大量的组件(迷宫能够领有很多墙或房间或门),而结构这个对象对其组件的应用又是不确定的这一问题(应用墙、房间、门的数量是不确定的),想要精密的管制构建过程,此时能够采纳建造者模式解决问题。

建造者模式的用意是为了结构对象,因而它属于创立型模式。

实用场景

  • 结构过程中,被结构的对象具备不同的示意。
  • 一些根本部件不会变,而其组合常常变动的时候。
  • 须要生成的对象外部属性自身相互依赖。

设计

指派一个建造者交给总指挥,由总指挥设计如何建造,由建造者理论建造,最终建造者将产品交给总指挥,用户从总指挥手中实现交付。

这样的流程是十分人性化的,例如咱们理论的房子装修也是如此,咱们请一些工人们,再请一个工人喽罗设计建造思路,领导这些工人该如何装修,咱们接下来只与工人喽罗打交道,由工人喽罗将装修好的房子交付给咱们。

代码示例

思考上述的迷宫问题:

// 定义迷宫类
class Maze {public void setRoom(int x, int y, int roomId) {System.out.println("在 [" + x + "," + y + "] 处建设一座编号为" + roomId + "的房间");
        // 保留相干信息
    }

    public void setDoor(int Id1, int Id2) {System.out.println("在组件编号为" + Id1 + "和组件编号为" + Id2 + "之间建设一扇门");
        // 保留相干信息
    }

    public void setBarrier(int x, int y, int barrierId) {System.out.println("在 [" + x + "," + y + "] 处建设一座编号为" + barrierId + "的障碍物");
        // 保留相干信息
    }
}

// 定义迷宫建造者接口
interface MazeBuilder {void buildRoom(int x, int y, int roomId);// 建造房间
    void buildDoor(int Id1, int Id2);// 建造门
    void buildBarrier(int x, int y, int barrierId);// 建造障碍物
    Maze getMaze();// 获取最终后果}

// 迷宫建造团队 A,每个建造团队的建造形式是不一样的
class MazeBuilderA implements MazeBuilder {
    // 建造团队将逐步完善这个迷宫,并交付给客户
    private Maze maze = new Maze();


    @Override
    public void buildRoom(int x, int y, int roomId) {maze.setRoom(x, y, roomId);
    }

    @Override
    public void buildDoor(int Id1, int Id2) {maze.setDoor(Id1, Id2);
    }

    @Override
    public void buildBarrier(int x, int y, int barrierId) {maze.setBarrier(x, y, barrierId);
    }

    @Override
    public Maze getMaze() {return maze;}
}

// 迷宫指挥者类
class MazeDirecotr {
    MazeBuilder mazeBuilder;

    public MazeDirecotr(MazeBuilder mazeBuilder) {this.mazeBuilder = mazeBuilder;}

    // 将工作交给指挥,用户只须要期待修建实现取走实例
    public Maze getMaze() {
        // 具体的设计思维在这里产生
        // 在这里咱们能够一步一步依照咱们的想法结构出简单的模型
        // 例如这里我想要建造两个房间和两头的一扇门
        mazeBuilder.buildRoom(0, 0, 0);
        mazeBuilder.buildRoom(0, 1, 1);
        mazeBuilder.buildDoor(0, 1);

        // 理论的工作是由工人们建造的
        // 总指挥从工人们手中获取最终产品,由总指挥实现与用户的交接
        return mazeBuilder.getMaze();}
}

// 测试类
public class Test {public static void main(String[] args) {
        // 请工人
        MazeBuilder mazeBuilder = new MazeBuilderA();

        // 请指挥,并将工人交给其指挥
        MazeDirecotr mazeDirecotr = new MazeDirecotr(mazeBuilder);

        // 最终与总指挥实现产品交付
        Maze maze = mazeDirecotr.getMaze();}
}
// 输入
/* 
在 [0,0] 处建设一座编号为 0 的房间
在 [0,1] 处建设一座编号为 1 的房间
在组件编号为 0 和组件编号为 1 之间建设一扇门
*/

通过建造者模式,咱们不再须要重载大量函数。通过设计导演类而一步一步的生成咱们冀望的对象,能够更加精密的管制创立的过程。理论开发中,导演类由用户本人编写定义,一个优化的技巧是采纳链式编程,咱们能够定义建造者接口如下:

// 定义迷宫建造者接口
interface MazeBuilder {MazeBuilder buildRoom(int x, int y, int roomId);// 建造房间
    MazeBuilder buildDoor(int Id1, int Id2);// 建造门
    MazeBuilder buildBarrier(int x, int y, int barrierId);// 建造障碍物
    Maze getMaze();// 获取最终后果}

那么咱们就能够在导演类中这样编写代码:

                                         mazeBuilder.buildRoom(0, 0, 0).buildRoom(0,1,1).buildDoor(0, 1);

优缺点总结

长处:

1、建造者独立,采纳接口方式,易扩大。

2、便于管制细节危险。

3、将设计与应用解耦,利于扩大与保护。

毛病:

1、产品必须有共同点,范畴有限度。

2、如外部变动简单,会有很多的建造类。

注意事项:与工厂模式的区别是:建造者模式更加关注与整机拆卸的程序。

退出移动版