0、背景


建造模式(Builder模式)

假如有一个需求:盖房子,盖房子过程是一致的:打桩、砌墙、封顶。但是房子是各式各样的,最后盖出来的房子可能是高楼或别墅。

根据直接的思路,不用设计模式思想,我们也许会:

  1. 写一个 CommonHouse 抽象类,然后里面规定了打桩、砌墙、封顶三个方法;
  2. 让不同房子继承这个类;
  3. 最后调用的时候调用分别的方法即可。

在继承抽象类、子类区分这一块,思想没有问题,问题出现这些类本身。

缺点:

过于简单,将产品(房子)和创建产品(房子建造流程)封装在了一起,耦合性增强了。(可以理解为,面向对象的思想里,房子虽然是一个类,拥有自己的方法,但是房子不应该拥有建造自己的方法)

解决方法:

解耦 - > 建造者模式。


一、建造者模式


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

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

建造者模式的四个角色:

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

他们之间的关系,我们用类图来解释:

  • Directer里面聚合一个Builder实际上使用的是他的实现类ConcreteBuilder;
  • ConcreteBuilder可以有很多,就是所谓的不同的房子的建造者。

因为getRusult是一样的,所以暂时不用接口,用抽象类实现Builder,代码如下:

/*
产品,对应product
*/
public class House {
private String base;
private String wall;
private String roof;
//对应getset方法
}
/*
抽象的建造者,对应Builder
*/
public abstract class HouseBuilder {
protected House house = new House();
//写好流程的各个方法,但不约束具体执行
public abstract void buildBasic();
public abstract void buildWalls();
public abstract void buildRoof();
//建造方法,返回建造结果
public House buildHouse(){
return house;
}
}
/*
普通房子制造流程,继承抽象类
可以看到,制造流程在这里,而House类拥有房子的属性,他们是分开的
应是对House的操作,这里省略
*/
public class CommonHouse extends HouseBuilder{
@Override
public void buildBasic() {
System.out.println("普通房子:建造地基。。。");
}
@Override
public void buildWalls() {
System.out.println("普通房子:砌墙。。。");
}
@Override
public void buildRoof() {
System.out.println("普通房子:盖屋顶。。。");
}
}
/*
另一个实现类,本来应是对House的操作,这里省略
*/
public class HighHouse extends HouseBuilder {
@Override
public void buildBasic() {
System.out.println("高楼:建造地基。。。");
}
@Override
public void buildWalls() {
System.out.println("高楼:砌墙。。。");
}
@Override
public void buildRoof() {
System.out.println("高楼:盖屋顶。。。");
}
}
/*
Director,聚合建造者HouseBuilder
同时决定制作流程,最后调用建造者的buildHouse方法返回
*/
public class Director {
HouseBuilder houseBuilder = null;
//通过构造器聚合
public Director(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
//通过setter方法聚合
public void setHouseBuilder(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
//指挥具体建造流程,先后顺序不由Builder决定
public House constructHouse(){
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.buildRoof();
return houseBuilder.buildHouse();
}
}
/*
客户端
*/
public class Client {
public static void main(String[] args) {
//new房子
CommonHouse commonHouse = new CommonHouse();
//new指挥者
Director director = new Director(commonHouse);
//完成盖房
House house = director.constructHouse(); //重置建造者
HighHouse highHouse = new HighHouse();
director.setHouseBuilder(highHouse);
House house1 = director.constructHouse();
}
}

上面代码总结起来:一是要把房子归为房子,有属性就够了,建造归建造,相当于是建筑工人,和房子两个对象分开,那么Director相当于包工头,对于不同的House要指挥不一样的Builder群体。


二、建造者模式在JDK中的应用


java.lang.StringBuilder类,也就是常用的可变字符串类,用到的就是建造者模式。以其中的常用方法 append 方法为例看源码。

2.1 Appendable 接口

定义了多个 append 方法(抽象方法),即 Appendable 就是我们的抽象建造者Builder 。

2.2 具体的实现类 AbstractStringBuilder

虽然也是一个抽象类,但是也已经实现了 Append able 接口的方法,所以其实相当于是具体的建造者ConcreteBuilder了;

2.3 StringBuilder,继承了AbstractStringBuilder

但是他重写 append 方法的方式只是调用了父类方法,所以应该说,StringBuilder既充当了Director,又是一个ConcreteBuilder.




三、注意事项


  1. 客户端不必知道产品呢内部组成的细节,将产品本身和产品的创建过程解耦,使得相同的创建过程可以创建不同的产品;
  2. 每一个具体的建造者都是相对独立的,和其他的建造者无关,因此可以方便替换具体建造者或者增加新的具体建造者,用户使用不同的具体建造者就能得到不同产品;
  3. 可以更加精细的控制创建过程;
  4. 增加新的具体建造者无需修改原有代码,指挥者针对抽象建造者编程;
  5. 建造者模式创建的产品,一定是共同点比较多,组成部分相似,如果产品之间的差异性很大,那么就不适合使用建造者模式,因此其适用范围受到一定的限制。

建造者模式 VS 抽象工厂模式:

抽象工厂模式实现对产品家族的创建,一个产品家族:具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产。

建造者模式是按照指定的要求创造产品,主要目的是通过组装零件产生一个新产品。

(可能有点模糊,但是个人认为本来就是模糊的。。只是一种设计思想,没有严格的边界。。。)

多多理解,就会清楚的!

设计模式:建造者模式及在jdk中的体现,建造者模式和工厂模式区别的更多相关文章

  1. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  2. 触发链模式之使用jdk的Observable和Observerver实现触发链模式(附JDK源码)

    首先看看JDK的Observer接口 public interface Observer { void update(Observable o, Object arg); } 也就一个更新的方法,这里 ...

  3. 设计模式之抽象工厂模式(Abstract Factory Pattern)

    一.抽象工厂模式的由来 抽象工厂模式,最开始是为了解决操作系统按钮和窗体风格,而产生的一种设计模式.例如:在windows系统中,我们要用windows设定的按钮和窗体,当我们切换Linux系统时,要 ...

  4. 设计模式之简单工厂模式(Simple Factory Pattern)

    一.简单工厂模式的由来 所有设计模式都是为解决某类问题而产生的,那么简单工厂模式是为解决什么问题呢?我们假设有以下业务场景: 在一个学生选课系统中,文科生用户选课时,我们要获得文科生的所有课程列表:理 ...

  5. GOF业务场景的设计模式-----工厂模式

    定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 工厂方法模式 基本代码 interface IProduct { public void produ ...

  6. (1)java设计模式之简单工厂模式

    一:简单工厂模式的优点          --->在阎宏博士的<JAVA与模式>一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Fa ...

  7. JAVA基础——设计模式之简单工厂模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式.简单工厂模式是由一个工厂 ...

  8. java面试题----工厂模式大整理(面试问的较多)

    在一次面试中了解到工厂模式在实际应用中的重要性,可以说工厂模式的应用随处可见,以下是百度百科对工厂模式的介绍 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式.著名的Jiv ...

  9. iOS开发-工厂模式

    工厂模式算是开发中比较常见的设计模式,简单工厂模式,工厂模式和抽象工厂模式,都属于工厂模式.简单工厂模式(simple factory)是类的创建模式,静态工厂方法(static factory me ...

随机推荐

  1. 修改虚拟机中的centos系统分辨率

    使用vmware虚拟机安装centos系统,默认分辨都很低,可使用以下方法修改虚拟机中centos系统的分辨率 1,# vi /boot/grub/grub.conf 2,找到 kernel 的那一行 ...

  2. Windows搭建Redis集群-详细教程

    一.集群知识 1.集群的概念 所谓的集群,就是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定.高效的状态. 2.使用redis集群的必要性 问题:我们已经部署好了redis,并且能启动 ...

  3. 014.Nginx跨域配置

    一 跨域概述 1.1 同源策略 同源策略是一个安全策略.同源,指的是协议,域名,端口相同.浏览器处于安全方面的考虑,只允许本域名下的接口交互,不同源的客户端脚本,在没有明确授权的情况下,不能读写对方的 ...

  4. Java历史[史上最详细的阐述了Java发展的历史过程]

    Java历史 学习Java语言之前,我觉得大家应该是从头开始,对吧?不管你之前是学过还是没学过,都和学习某一个知识一样,从头开始去了解它,然后到这个深入的掌握,到最后你可能理解并且灵活的运用.所以它肯 ...

  5. STL源码剖析:序列式容器

    前言 容器,置物之所也.就是存放数据的地方. array(数组).list(串行).tree(树).stack(堆栈).queue(队列).hash table(杂凑表).set(集合).map(映像 ...

  6. 004.Nginx日志配置及状态监控

    一 Nginx请求简介 1.1 请求头部 对于HTTP而言,客户端负责发起request请求,服务端负责response响应. request:包括请求行.请求头部.请求数据: response:包括 ...

  7. SQL Server数据类型对应.Net Core中的数据类型

    SQL C# bigint(sql大小:8byte) long(64位) int, integer(sql大小:4byte) int(32位) smallint(sql大小:2byte) short( ...

  8. Markdown画图(mermaid)学习

    简介 目前博客园支持mermaid的graph,subgraph,sequenceDiagram,gantt,classDiagram mermaid(美人鱼), 是一个类似markdown,用文本语 ...

  9. Jarvisoj-web phpinfo

    题目入口:http://web.jarvisoj.com:32784/ 一进来就看到源码 简单分析之后知道考点是反序列化,注意到了关键字session_start(),这个函数是用于创建会话.但具体如 ...

  10. Google免费新书-《构建安全&可靠的系统》

    前段时间riusksk在公众号分享的Google安全团队的新书,好书,全英原版,开源免费. 免费下载地址:https://static.googleusercontent.com/media/land ...