开篇废话

周末因懒的原因,停更了两天。今天主要研究建造者模式。畅游各大博客网站,推荐一篇关于建造者模式的博客http://blog.csdn.net/self_study/article/details/51707029,简单明了,条例清晰。如果看不懂我写的,可以尝试去看看别人的。。。

什么是建造者模式

讲建造者模式,这里要提取几个关键词:

复杂对象: 这里简单的体现可以理解为,这里对象的成员数量很多,所以它很复杂。

构建过程: 对成员对象进行赋值,业务逻辑生成等一系列使之成为一个成熟的对象。

表示: 返回这个对象。

构建过程与表示分离: 一般来说,对成员对象的赋值通常在构造函数中,这种方式除了不够灵活之外,还有就是如果成员对象过多,因为构造函数就会显得十分臃肿。所以,我们可以将构建过程(简单的理解为赋值,这里不严谨,只是为了帮助理解概念)封装成独立的方法,然后再返回整个需要的实例对象。

那么建造者模式:就是为了解决生成复杂对象的问题,主要通过将构建过程与表示分离的方法。

如何实现建造者模式

理解了建造者模式后,我们来实现它,就相对简单了。

首先盗图一张:

建造者模式类图

可以看到,这里呈现了四个类,有时候实际开发中会将这个模型进行简化,我们这里先学习理论,因为实际操作时,灵活变动太多了,不适合讲解。但是万变不离其宗,核心思想就是这些。

Product,都称这个为产品类,说白了就是我需要生成的类。

Builder类,这是一个抽象类或者接口,用来规定构建对象的所需方法。

ConcreteBuilder 对builder的抽象方法的实现类,通常对其优化为product的内部类,从而省掉builder的定义。常见的有 AlertDialog.Builder 。

Director 调用concrete的方法的类。一般来说,使用的建造者模式时,这个也给省了。

我们先来看一个完整版的。以造汽车为例,现在我们需要一辆,有四个轮子,有四个座椅,有防风玻璃,有方向盘,发动机等等(这里只列举这几样)。

首先我们先看Product类,就是我们要生成的复杂对象,这里就是指小汽车。

public class Car {

List tyres = new ArrayList<>();

List carMounts = new ArrayList<>();

String glass;

String steeringWheel;

String engine;

public void setTyres(String tyres) {

this.tyres.add(tyres);

}

public void setCarMounts(String carMounts) {

this.carMounts.add(carMounts);

}

public void setGlass(String glass) {

this.glass = glass;

}

public void setSteeringWheel(String steeringWheel) {

this.steeringWheel = steeringWheel;

}

public void setEngine(String engine) {

this.engine = engine;

}

public List getTyres() {

return tyres;

}

public List getCarMounts() {

return carMounts;

}

public String getGlass() {

return glass;

}

public String getSteeringWheel() {

return steeringWheel;

}

public String getEngine() {

return engine;

}

}

这里可以看到小汽车有五个属性,然后通过setter和getter方法来对属性赋值。

然后我们先看Builder类,这是一个抽象类或者接口,具体使用看情况而定,我今天想用接口表示:

public interface Builder {

public void buildeTyre(int wheelNumber);

public void buildCarMounts(int carMountsNumber);

public void buildGalss();

public void buildSteeringWheel();

public void buildEngine();

public Car build();

}

这里定义了五个造小汽车零件的方法,和一个生成对象方法,因为你不能只造这些零件,还需要把这些零件给组装起来啊。

紧接着我们需要ConcreteBuilder类来实现这些方法啊,毕竟我们是实干家,不能光说不做!concretebuilder

public class CarBuilder implements Builder {

Car car = new Car();

@Override

public void buildeTyre(int wheelNumber) {

for (int i = 0; i < wheelNumber; i++) {

car.setTyres("已经造了" + i + "轮子了");

}

}

@Override

public void buildCarMounts(int carMountsNumber) {

for (int i = 0; i < carMountsNumber; i++) {

car.setCarMounts("已经造了" + i + "椅子了");

}

}

@Override

public void buildGalss() {

car.setGlass("防风玻璃做好了");

}

@Override

public void buildSteeringWheel() {

car.setSteeringWheel("方向盘做好了");

}

@Override

public void buildEngine() {

car.setEngine("发动机已经做好了");

}

@Override

public Car build() {

return car;

}

}

这里实现了builder接口,没什么好说的,值得注意的就是,在CarBuilder类中,维护了一个Car对象,实现的所有方法中,去调用Car的set方法,最后build()方法中去返回这个对象。

此时此刻,我们已经能通过CarBuilder类去建造我们所需要的Car对象了。但是毕竟造汽车的工序是及其复杂了,因为我们这里只简单的列举了五项,可能感觉还是比较轻松的,但是,如果有上百道工序的话,难道我们需要每次去造小车的时候都去调用这上百个方法吗。显然,这里构建的过程,我们希望是不透明的,那么我们可以将这个步骤封装起来,于是就有了Director类的出现。

我们希望有一个技术总工来调度负责整个造车的过程。

public class AodiDirecter {

private Builder builder;

public AodiDirecter(Builder builder) {

this.builder = builder;

}

public void construct() {

builder.buildeTyre(4);

builder.buildCarMounts(4);

builder.buildEngine();

builder.buildGalss();

builder.buildSteeringWheel();

}

}

这样整个建造者模式就完成了,而我们需要一个奥迪车时,只需要:

public class Buyer {

public void buy() {

Builder builder = new CarBuilder();

AodiDirecter director = new AodiDirecter(builder);

director.construct();

Car aodiCar = builder.build();

}

}

如果说,builder是产线工人们,AodiDirecter 就可以理解为奥迪工程师,工人们只知道制造器件,工程师来统筹设计造车的工序,安排下去后,工人们按命令执行就行了。而对于买家来说,我并看不到你是怎么造的,反正我只要结果就行了。

但是这样往往会很麻烦,我们通常会对其进行精简优化。

看上面对建造者定义了四个功能模块,在实现过程中,是不是有一些,何必多此一举的感觉。这里我盗用了别人的代码,工作繁忙(太懒了)还请谅解。

public class Computer {

private String CPU;

private String GPU;

private String memoryType;

private int memorySize;

private String storageType;

private int storageSize;

private String screenType;

private float screenSize;

private String OSType;

public static class Builder {

// Optional parameters - initialize with default values

private String CPU = "inter-i3";

private String GPU = "GTX-960";

private String memoryType = "ddr3 1666MHz";

private int memorySize = 8;//8GB

private String storageType = "hdd";

private int storageSize = 1024;//1TB

private String screenType = "IPS";

private float screenSize = 23.8f;

private String OSType = "Windows 10";

public Builder() {

}

public Builder setCPU(String CPU) {

this.CPU = CPU;

return this;

}

public Builder setGPU(String GPU) {

this.GPU = GPU;

return this;

}

public Builder setMemoryType(String memoryType) {

this.memoryType = memoryType;

return this;

}

public Builder setMemorySize(int memorySize) {

this.memorySize = memorySize;

return this;

}

public Builder setStorageType(String storageType) {

this.storageType = storageType;

return this;

}

public Builder setStorageSize(int storageSize) {

this.storageSize = storageSize;

return this;

}

public Builder setScreenType(String screenType) {

this.screenType = screenType;

return this;

}

public Builder setScreenSize(float screenSize) {

this.screenSize = screenSize;

return this;

}

public Builder setOSType(String OSType) {

this.OSType = OSType;

return this;

}

public Computer create() {

return new Computer(this);

}

}

private Computer(Builder builder) {

CPU = builder.CPU;

GPU = builder.GPU;

memoryType = builder.memoryType;

memorySize = builder.memorySize;

storageType = builder.storageType;

storageSize = builder.storageSize;

screenType = builder.screenType;

screenSize = builder.screenSize;

OSType = builder.OSType;

}

}

可以看到,整个建造者模式就是一个类,然而这个类中存在一个静态内部类Builder,这个Builder,其实对应的是建造者模式中的concreteBuilder,Computer对应的就是我们product。去掉了Builder抽象类,因为直接实现了。同时还缺少了Directer,因为这里的设计是暴露构建细节,所以就不需要了。

这种方式的好处就是,过程可控。我们来看看调用。

Computer computer = new Computer.Builder()

.setCPU("inter-skylake-i7")

.setGPU("GTX-Titan")

.setMemoryType("ddr4-2133MHz")

.setMemorySize(16)

.setStorageType("ssd")

.setStorageSize(512)

.setScreenType("IPS")

.setScreenSize(28)

.setOSType("Ubuntu/Window10")

.create();

这是一种链式调用,也是我们常见的建造者模式。我们可以对每个成员对象进行控制,从而得到我们想要的product。当然,我们看回Computer类的实现,发现,每个成员对象都是有个默认值的。也就是说,你完全可以通过new Computer.Builder().create()来获取默认的实例对象,这基本就是Directer的功能。所以精简下来,发现建造者模式还是挺实用的。

然而在大型的系统中,精简版的建造者模式,并不是很适用,因为它的针对性太强,往往呈现出来的是同一种产品,拓展性并不是很好,而我们使用原始版的话,可以对Directer进行拓展,可以更加多元灵活。

java设计模式 建造模式_java设计模式(三)建造者模式相关推荐

  1. Java创新型模式_java设计模式--创建型模式(一)

    2016-04-24 10:10:34 创建型模式:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 注意:工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂 ...

  2. 设计模式C++实现(6)——建造者模式

    软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径.设计模式中运用了面向对象编程语言的重要特性:封装.继承.多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累.最 ...

  3. 设计模式C++实现(3)——建造者模式

    软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径.设计模式中运用了面向对象编程语言的重要特性:封装.继承.多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累.最 ...

  4. 【设计模式2022】第六章 建造者模式

    [设计模式2022]第六章 建造者模式 文章目录 [设计模式2022]第六章 建造者模式 一.建造者模式 1.结构 2.案例 3.分析 4.使用场景 5.扩展 6.对比工厂模式 一.建造者模式 将一个 ...

  5. java设计模式中不属于创建型模式_Java设计模式(5)——创建型模式之建造者模式(Builder)...

    一.概述 概念 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.(与工厂类不同的是它用于创建复合对象) UML图 主要角色 抽象建造者(Builder)--规范建造方法与结果返还 ...

  6. java web简单工厂模式_JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)

    在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的.但是在一些情况下, new操作符直接生成对象会带来一些问题.举例来说, 许多类型对象的创造需要一 ...

  7. java解耦的模板模式_Java 设计模式(9) —— 模板模式

    一.模板模式 封装了一个算法步骤,并允许子类为一个或多个步骤方法提供实现.模板模式可以使子类在不改变算法结构的情况下,重新定义算法中的某些步骤. 模板模式 二.示例 泡咖啡与泡茶: 泡咖啡的步骤: 水 ...

  8. java 设置模式_Java设计模式百例 - 调停者模式

    调停者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性的.这种模式提供了一个调停者类,用来充当"中心化"或"总线化"的角色,与各个 ...

  9. JAVA设计模式是个什么玩意儿_04_建造者模式

    1. 说明 (1)英文名叫Builder,建造者模式,也叫生成器模式. (2)属于创建型模式. 2. 定义 要想实现同样的构建过程有不同的表现,自然的思路就是把构建过程独立出来,在生成器模式中把它称为 ...

最新文章

  1. 深度神经网络对脑电信号运动想象动作的在线解码
  2. [YTU]_2625( 构造函数和析构函数)
  3. CTFshow 反序列化 web254
  4. NB驱动层MQTT发布和订阅数据的代码实现
  5. 微软想将新版Edge浏览器引入Linux
  6. JAVA知识基础(三):修饰符
  7. MySQL8怎么设置时区为东八区_mysql时区设置为东八区
  8. Java基础学习总结(167)——Java项目实践中如何实现幂等
  9. 程序员疯狂记事:如何利用众多技术栈构建一个 Web 应用程序?!
  10. nginx强制刷新用户缓存_HTTP 缓存
  11. Struts2概述及与Struts1的对比
  12. 技能 | 制作excel版学生成绩分析表
  13. 数据结构——栈与队列的异同
  14. 注册表常用命令DOS
  15. 计算机硬件系统主机主要包括,组成计算机硬件系统的基本部分是什么?
  16. JAVA爬取淘宝、京东、天猫以及苏宁商品历史价格(二)
  17. Java web网页版仿QQ实现在线聊天功能系统
  18. keil遇到FCARM - Output Name not specified, please check ‘Options for Target - Utilities‘解决方法
  19. ext3格式化成ext4
  20. 关于video标签,禁止点击播放时自动全屏,和video出现诡异窗口重叠

热门文章

  1. 数据结构 三:树(Tree)
  2. Client MFC application解决办法
  3. SolidWorks 2023软件安装教程SW2023软件安装包
  4. 小马哥----高仿苹果6S A235刷机拆机图与开机界面图 真八核6735芯片 精仿系列机
  5. 【数据挖掘】2022数据挖掘之Matplotlib完整使用(折线图、散点图、柱状图、直方图、饼图)
  6. nextvlad:一个用于大规模视频分类的聚集帧级特征的有效神经网络 NeXtVLAD: An Efficient Neural Network toAggregate Frame-level Fea
  7. vue2中watch的使用
  8. Python 将一个已知的 utc时间字符串 转换为东八区时间
  9. 帝国时代3如何快速实现低成本训练领事馆其它兵种
  10. 2021年保育员(中级)考试题及保育员(中级)考试报名