摘要:建造者模式(Builder Pattern)又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

本文分享自华为云社区《【Java设计模式】用盖房子案例讲解建造者模式(生成器模式)》,作者: 我是一棵卷心菜 。

现在我们需要建房子,过程为打桩、砌墙、封顶。房子有各种各样的,比如普通房,高楼,别墅,各种房子的过程虽然一样,但是要求不要相同的。请编写程序,完成需求

传统方式

1、类图分析

2、代码分析

先创建一个抽象类AbstractHouse,具有打地基、砌墙、封装屋顶以及建房子的功能

public abstract class AbstractHouse {
//打地基
public abstract void buildBasic();
//砌墙
public abstract void buildWalls();
//封装屋顶
public abstract void roofed();
//开始建房子
public void build() {
buildBasic();
buildWalls();
roofed();
}
}

然后选择自己想建造的房子,我选择的是普通的房子,对应类CommonHouse

public class CommonHouse extends AbstractHouse {
@Override
public void buildBasic() {
System.out.println("普通房子开始打地基");
}
@Override
public void buildWalls() {
System.out.println("普通房子开始建墙了");
}
@Override
public void roofed() {
System.out.println("普通房子准备封顶喽");
}
}

最后写一个类Client用来检测结果

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

3、代码结果

4、问题分析

优点是比较好理解,简单易操作。

缺点是设计的程序结构过于简单,没有设计缓存层对象,程序的扩展和维护不好。也就是说,这种设计方案,把产品(即房子)和创建产品的过程(即建房子流程) 封装在一起,耦合性增强了。

建造者模式

1、基本介绍

建造者模式(Builder Pattern)又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

2、四个角色

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

3、类图分析

4、代码分析

先创建一个房子类House,具有打地基、砌墙和封装屋顶的功能

public class House {
private String baise;
private String wall;
private String roofed;
public String getBaise() {
return baise;
}
public void setBaise(String baise) {
this.baise = baise;
}
public String getWall() {
return wall;
}
public void setWall(String wall) {
this.wall = wall;
}
public String getRoofed() {
return roofed;
}
public void setRoofed(String roofed) {
this.roofed = roofed;
}
}

接着创建抽象的建造者HouseBuilder

public abstract class HouseBuilder {
public House house = new House();
//将建造的流程写好,抽象的方法
public abstract void buildBasic();
public abstract void buildWalls();
public abstract void roofed();
//建造房子好后,将产品(房子)返回
public House buildHouse() {
return house;
}
}

然后创建指挥者HouseDirector,动态的指定制作流程,返回产品

public class HouseDirector {
HouseBuilder houseBuilder = null;
//空参构造器
public HouseDirector() {
}
//通过setter传入houseBuilder
public void setHouseBuilder(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
//如何处理建造房子的流程,交给指挥者
public House constructorHouse() {
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.roofed();
return houseBuilder.buildHouse();
}
}

刚才建造的是普通的房子,现在我想要建造一个高楼类HighBuilding

public class HighBuilding extends HouseBuilder {
@Override
public void buildBasic() {
System.out.println("高楼房子开始打地基");
}
@Override
public void buildWalls() {
System.out.println("高楼房子开始建墙了");
}
@Override
public void roofed() {
System.out.println("高楼房子准备封顶喽");
}
}

最后写一个类用来测试

public class Client {
public static void main(String[] args) {
//准备创建房子的指挥者
HouseDirector houseDirector = new HouseDirector();
//盖高楼
HighBuilding highBuilding = new HighBuilding();
//重置建造者
houseDirector.setHouseBuilder(highBuilding);
//完成盖房子,返回产品(高楼)
houseDirector.constructorHouse();
}
}

5、代码结果

6、注意事项

  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象
  • 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合 “开闭原则”
  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,因此在这种情况下,要考虑是否选择建造者模式.

总结

那么抽象工厂模式与建造者模式有什么不同点呢?

抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品,由什么工厂生产即可。而建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。

点击关注,第一时间了解华为云新鲜技术~

今儿直白的用盖房子为例,给你讲讲Java建造者模式的更多相关文章

  1. tyvj1189 盖房子

    描述 永恒の灵魂最近得到了面积为n*m的一大块土地(高兴ING^_^),他想在这块土地上建造一所房子,这个房子必须是正方形的.但是,这块土地并非十全十美,上面有很多不平坦的地方(也可以叫瑕疵).这些瑕 ...

  2. 【动态规划】盖房子(house)--未提交--已提交

    问题 D: 盖房子(house) 时间限制: 1 Sec  内存限制: 64 MB提交: 27  解决: 16[提交][状态][讨论版] 题目描述 FJ最近得到了面积为n*m的一大块土地,他想在这块土 ...

  3. 盖房子(house)

    盖房子(house) 题目描述 FJ最近得到了面积为n*m的一大块土地,他想在这块土地上建造一所房子,这个房子必须膏形的.但是,这块土地并非十全十美,上面有很多不平坦的地方(也可以叫瑕疵).这些瑕疵十 ...

  4. vijos 1057 盖房子 简单DP

    描述 永恒の灵魂最近得到了面积为n*m的一大块土地(高兴ING^_^),他想在这块土地上建造一所房子,这个房子必须是正方形的. 但是,这块土地并非十全十美,上面有很多不平坦的地方(也可以叫瑕疵).这些 ...

  5. vijos 1057 盖房子 dp 最大子正方形

    P1057盖房子 未递交 标签:[显示标签] 描述 永恒の灵魂最近得到了面积为n*m的一大块土地(高兴ING^_^),他想在这块土地上建造一所房子,这个房子必须是正方形的. 但是,这块土地并非十全十美 ...

  6. Vijos 1057 盖房子

    二次联通门 : Vijos 1057 盖房子 /* Vijos 1057 盖房子 简单的dp 当前点(i, j)所能构成的最大的正方形的边长 为点(i - 1, j - 1)与(i, j - 1), ...

  7. ECNU 2018 10月月赛 E 盖房子 (bitset + 倍增)

    题目链接  ECNU Monthly 2018.10 Problem E 从开场写到结束…… 显然要把三角形分成上下两部分. 把每一部分分成三部分,以上部分为例. 上面和右边,以及左下角的正方形. 也 ...

  8. 模拟赛01 T3 盖房子

    题面 http://zhengruioi.com/problem/248 题解 三重容斥(说是两重也行吧) 我们来看题目的约束 ①有k个位置不能放(k≤8) ②每行每列至少一个 ③正负对角线至少一个 ...

  9. Vijos1057 盖房子(DP经典题)

    之前没有怎么刷过dp的题,所以在此学习了~(感谢walala大神的思路,给了我很大的启发) 也算是自己学习的另一种dp题型吧 先贴上状态转移方程: if(a[i][j]) f[i][j]=min(f[ ...

随机推荐

  1. 【问题排查过程】vm-backup的snapshots导致磁盘满

    使用中发现,vm-storage节点仅仅过了6天,就占用了800GB的硬盘空间.很不正常.下面是排查过程: 1.查看磁盘占用情况: 先登录容器,执行: df -h /dev/vdb 1012.8G 8 ...

  2. 【采坑小计】prometheus的remote write协议遇到的问题

    没有读懂源码以前,无脑试错总是效率很低的! 1.thanos receiver报store locally for endpoint : conflict 接口返回的日志: store locally ...

  3. gin中映射查询字符串或表单参数

    package main import ( "fmt" "github.com/gin-gonic/gin" ) func main() { r := gin. ...

  4. Go 转义字符及风格

    今天来学习一下Go 中的转义字符,源码注释,规范的代码风格以及标准库API 文档; Go 转义字符常用的转义字符有以下几个:1. \t: 表示一个制表符(tab), 通常可以使用它进行排版; 2. \ ...

  5. Linux创建运行C/C++代码

    不同于在Windows操作系统下借助IDE运行C++程序,Linux操作系统可以使用g++编译 创建文件及编译文件的流程  1. 先进入某一文件目录下,创建一个文件(也可以用mkdir创建文件) to ...

  6. iptables规则管理

    查看规则 iptables -t filter -L INPUT -n -v --line  省略-t选项时,表示默认操作filter表中的规则 添加规则 注意点:添加规则时,规则的顺序非常重要  - ...

  7. Android开发----EditText&ImageView&第三方库的加载

    EditText组件 一个实例描述该组件的全部属性(虚假的登录界面) 在activity.xml中 <?xml version="1.0" encoding="ut ...

  8. rm误操作 which查看命令存放路径

    目录 一:rm误操作 which查看命令存放路径 一:rm误操作 which查看命令存放路径 解决rm命令误操作 让别人使用不了自己的rm命令 将rm命令改一个名称 mv rm abc 查看命令存放路 ...

  9. 在Linux虚拟机上挂载文件卷

    一 通过跳板机 将卷挂载在ec2 实例上的方法. 1 查询 机器上挂载了那些卷? // lsblk 是否已经是挂载卷 查看后面的目录 如果没有就是未挂载. 2 操作未挂载卷? /* sudo file ...

  10. Android中ActionBar和ToolBar添加返回箭头

    感谢大佬:https://blog.csdn.net/baidu_32682229/article/details/77927745 ActionBar添加返回箭头 //onCreate方法中 Act ...