java设计模式之建造者模式

2023-11-07

定义:

建造者模式将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示,属于创建型设计模式

对于用户而言,使用建造者模式只需指定需要创建的类型就可以获得对象,创建过程及细节不需要了解。根据建造者模式的定义,可以简单的理解为两层含义。

  1. 构建与表示分离:构建代表对象创建,表示代表对象行为,方法。也就是将对象的创建与行为进行分离(对应到java代码,其实就是使用接口规定行为,然后由具体的实体类进行构建)

  2. 创建不同表示:也就是具备同样的行为,但是却由于构建的行为顺序不同或其他原因可以创建出不同的表示

应用场景:

从定义来看,建造者模式和工厂模式是非常相似的,和工厂模式一样,具备创建与表示分离的特性。建造者模式唯一区别与工厂模式的是针对复杂对象的创建,也就是说,如果创建简单对象,通常使用工厂模式进行创建,而如果复杂的对象,就可以考虑使用建造者模式。

当需要创建产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,是创建产品的灵活性大大增加,建造者模式主要用于以下场景

  1. 相同的方法,不同的执行顺序,产生不同的结果

  2. 多个部件或零件,都可以装配到一个对象中,但是产生的结果有不相同

  3. 产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用

  4. 初始化一个对象特别复杂,参数多,而且很多参数都具有默认值

UML类图:

 

右上图可以看到,建造者模式主要包含四个角色

  1. 产品(Product):要创建产品类对象

  2. 抽象建造者(IBuilder):建造者的抽象类,规范产品对象的各个组成部分的创建,一般由子类实现具体的创建过程

  3. 建造者(ConcreteBuilder):具体的Builder类,根据不同的业务逻辑,具体化对象的各个组成部分的创建

  4. 调用者(Director):调用具体的建造者,来创建对象的各个部分,在指导者中不涉及具体产品的信息,自负责保证对象各部分完整创建或者按照某种顺序创建。在类图中,相当于client的角色

通用写法:

package com.design.pattern.builder;
​
public class Client {
    public static void main(String[] args) {
        IBuilder builder = new ConcreteBuilder();
        System.out.println(builder.build());
    }
}
package com.design.pattern.builder;
​
public class ConcreteBuilder implements IBuilder{
    public Product product = new Product();
    @Override
    public Product build() {
        return product;
    }
}
package com.design.pattern.builder;
​
public interface IBuilder {
    Product build();
}
package com.design.pattern.builder;
​
public class Product {
    public String name;
​
    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                '}';
    }
}

使用建造者模式解决实际问题:

建造者模式的链式写法:

以课程为例,一个完整的课程有PPT课件,回放视频,课堂笔记,课后作业组成,但是这些内容的设置顺序可以随意调整,我们用建造者模式来带入理解一下。首先创建一个产品类Course

package com.design.pattern.builder;
​
import lombok.Data;
​
@Data
public class Course {
    private String name;
    private String ppt;
    private String videos;
    private String note;
​
    private String homework;
​
    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                ", ppt='" + ppt + '\'' +
                ", videos='" + videos + '\'' +
                ", note='" + note + '\'' +
                ", homework='" + homework + '\'' +
                '}';
    }
}

然后创建建造者类CourseBuilder,将复杂的创建过程封装起来,创建步骤由用户决定

package com.design.pattern.builder;
​
public class CourseBuilder {
    private Course course = new Course();
    public CourseBuilder addName(String name){
        course.setName(name);
        return this;
    }
    public CourseBuilder addPpt(String ppt){
        course.setPpt(ppt);
        return this;
    }
    public CourseBuilder addVideo(String video){
        course.setVideos(video);
        return this;
    }
    public CourseBuilder addNote(String note){
        course.setNote(note);
        return this;
    }
    public CourseBuilder addHomeWork(String homeWork){
        course.setHomework(homeWork);
        return this;
    }
    public Course builder(){
        return course;
    }
}

最后编写客户端测试代码:

package com.design.pattern.builder;
​
public class BuilderTest {
    public static void main(String[] args) {
        CourseBuilder courseBuilder = new CourseBuilder().addName("设计模式")
                .addNote("note")
                .addPpt("ppt")
                .addVideo("video")
                .addHomeWork("homeWork");
        System.out.println(courseBuilder.builder());
    }
}

静态内部类实现建造者模式

一般情况下,我们更习惯使用静态内部类的方式实现建造者模式,即一个产品类内部自动带有一个具体建造者,由它负责该产品的组装创建,不再需要Builder和director,这样产品表示与创建之间的联系更加紧密,结构更加紧凑,同时是的建造者模式的形式更加简洁

使用静态内部类的方式,前面的案例可以改写为:

package com.design.pattern.builder;
​
public class Course2 {
    private String name;
    private String ppt;
    private String videos;
    private String note;
​
    private String homework;
​
    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                ", ppt='" + ppt + '\'' +
                ", videos='" + videos + '\'' +
                ", note='" + note + '\'' +
                ", homework='" + homework + '\'' +
                '}';
    }
    public static class Builder{
        private Course course = new Course();
        public Builder addName(String name){
            course.setName(name);
            return this;
        }
        public Builder addPpt(String ppt){
            course.setPpt(ppt);
            return this;
        }
        public Builder addVideo(String video){
            course.setVideos(video);
            return this;
        }
        public Builder addNote(String note){
            course.setNote(note);
            return this;
        }
        public Builder addHomeWork(String homeWork){
            course.setHomework(homeWork);
            return this;
        }
        public Course builder(){
            return course;
        }
    }
}

客户端测试代码:

package com.design.pattern.builder;
​
public class StaticBuilderTest {
    public static void main(String[] args) {
        Course builder = new Course2.Builder().addName("设计模式")
                .addNote("note")
                .addPpt("ppt")
                .addVideo("video")
                .addHomeWork("homeWork")
                .builder();
        System.out.println(builder);
​
    }
}

这样代码看上去更加简洁,不会让人感觉到多了一个类

建造者模式与工厂模式的区别

  1. 建造者模式更注重方法的调用顺序,工厂模式更注重创建对象

  2. 创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样

  3. 关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成

  4. 建造者模式根绝建造过程中的顺序不一样,最终的对象部件组成也不一样

建造者模式的优点:

  1. 封装性好,构建和表示分离

  2. 扩展性好,建造类之间独立,在一定程度上接偶

  3. 便于控制细节,建造者可以对创建过程逐步细化,而不对其他模块产生任何影响

建造者模式的缺点:

  1. 需要多创建一个Builder对象

  2. 如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java设计模式之建造者模式 的相关文章

随机推荐

  • 启明云端分享

    提示 作为Espressif 乐鑫科技 大中华区合作伙伴及sigmastar 厦门星宸 VAD合作伙伴 启明云端不仅用心整理了你在开发过程中可能会遇到的问题以及快速上手的简明教程供开发小伙伴参考 同时也用心整理了乐鑫及星宸科技的新产品 新方
  • 虚拟主机的数据库服务器怎么填,虚拟主机的数据库服务器怎么填

    虚拟主机的数据库服务器怎么填 内容精选 换一换 华为云提供两种连接方式通过SQL Server客户端连接实例 非SSL连接和SSL连接 其中 SSL连接实现了数据加密功能 具有更高的安全性 安装SQL Server客户端请参见如何安装SQL
  • 2019 ICPC香港站 G. Game Design

    Problem G Codeforces 问题描述 怪物只能在树叶子节点出生 向上走 可以花费一个值在一个节点建防御塔 防御塔会阻碍怪物向上走 最小花费可以让根节点无法被怪物走到的一个造塔方法算是一个方案 现给定方案数 让构造满足给定方案数
  • Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when tryin

    多线程在更新数据库时报死锁问题 死锁信息 1 TRANSACTION TRANSACTION 29285454235 ACTIVE 0 001 sec fetching rows mysql tables in use 3 locked 3
  • 微信小程序iOS虚拟支付问题汇总

    一 做了一款在线听课的小程序 是否涉及到小程序虚拟支付的问题 是 影响最大的还是那些把IOS会员当做变现唯一手段的小程序 如果小程序只是服务老用户 拉新 裂变等较少 影响自然少一点 二 什么是虚拟支付 虚拟支付是指购买非实物商品 摸不到的物
  • 剑指 Offer 28. 对称的二叉树(递归/并且或者要考虑好)

    orz 没有思路 有了思路还是错的 递归 可以仿照归并排序 我这么觉得 两边判断 如果不是当我没说 递归停止的条件是什么 结束条件 左节点和右节点都为空 gt 倒底了都长得一样 gt true 左节点为空的时候右节点不为空 或反之 gt 长
  • Harbor仓库介绍与搭建过程

    一 介绍 Harbor 是一个英文单词 意思是港湾 港湾是干什么的呢 就是停放货物的 而货物呢 是装在集装箱中的 说到集装箱 就不得不提到Docker容器 因为docker容器的技术正是借鉴了集装箱的原理 所以 Harbor正是一个用于存储
  • 代码块和执行顺序

    1 什么是代码块 使用 定义的一段代码我们称之为代码块 一般分为 1 普通代码块 2 实例代码块 3 静态代码块 2 普通代码块 定义在方法中的代码块 可以用于限定局部变量的生命周期 public class Main public sta
  • 决策树的实现原理与matlab代码

    很久不写博客了 感觉很长一段时间只是一味的看书 疏不知一味地看书 写代码会导致自己的思考以及总结能力变得衰弱 所以 我决定还是继续写博客 废话不多说了 今天想主要记录数据挖掘中的决策树 希望能够将自己的理解写得通俗易懂 决策树是一种对实例分
  • windows使用cmd运行jar点击黑窗口项目停止运行问题

    windows使用cmd运行jar点击黑窗口项目停止运行问题 问题 解决 问题 近期做的项目部署在windows服务器下 使用cmd运行jar包的方式 出现项目停了运行问题 原因是误点击了黑窗口里的位置 导致项目停止运行 解决 取消勾选即可
  • java数组 contains_java怎么判断一个元素是否在数组中存在

    我是前端出身 写这个判断是否存在或者是去重的方法 前端js基本上有好多种方法 但是貌似都有点麻烦 js与Java其实也大差不差 只要思路正确 只是实现的代码不同罢了 起初我想的是通过双层for循环 但貌似依旧有点麻烦 查工具书发现 Java
  • 增强for循环

    package structure loop 增强for循环 重点是用来循环数组和集合的 public class ForDemo05 public static void main String args int nembers 5 2
  • 锂电池的充电原理

    一 锂电池的充电原理 锂离子电池的充电过程可以分为三个阶段 涓流充电 低压预充 恒流充电 恒压充电 锂电池的充电方式是限压恒流 都是由IC芯片控制的 典型的充电方式是 先检测待充电电池的电压 如果电 压低于3V 要先进行预充电 充电电流为设
  • 微信电脑版不断崩溃

    目录 文章背景 目录 问题介绍 解决问题 说明 参考文章 版本记录 文章背景 之前不知道为什么 突然发生微信不断崩溃的状况 更新微信没用尝试网上的各种方法都没用 不过索性最后解决了 想看解决方案的话看最后了 中间记录的是崩溃日志 目录 问题
  • nrm 安装后报错

    Error ERR REQUIRE ESM require of ES Module D npm node modules nrm node modules open index js from D npm node modules nrm
  • python async 异步

    1 requests 包不支持异步 使用 requests async import asyncio import threading import time from aiohttp import ClientSession import
  • g++配置选项-std=c++11

    如何配置g 选项 std c 11 g 命令改为 g std c 11 qt配置std的c 11 QMAKE CXXFLAGS std c 11 如果没有配置c 11 就会报如下错
  • Comparable、compareTo、Comparator、compare之间有什么区别

    Comparable和Comparator是Java的接口 而compareTo是Comparable接口中的方法 compare是Comparator中的方法 在Scala中Ordered相当于Java中的Comparable 在Scal
  • UML2面向对象分析与设计(第2版) 谭火彬 杂记

    首先 来讲讲我对泛化的理解 其实这是站在的视角的不同而表述的不同 泛化是站在父类的角度 父类给孩子的方式叫泛化 而继承是站在孩子的角度 儿子继承父类的方式叫继承 其实上了谭老师大概一章的课程 并且我觉得谭老师真的是对面向对象很有认识的 这门
  • java设计模式之建造者模式

    定义 建造者模式将一个复杂对象的构建过程与它的表示分离 使得同样的构建过程可以创建不同的表示 属于创建型设计模式 对于用户而言 使用建造者模式只需指定需要创建的类型就可以获得对象 创建过程及细节不需要了解 根据建造者模式的定义 可以简单的理