设计模式(七)创建者模式之建造者模式

news2024/11/28 8:36:02

这里写目录标题

  • 概述
  • 需求
  • 需求类图
    • Bike
    • Builder
    • MobikeBuilder
    • OfoBuilder
    • Director
    • Client
    • Client
    • 优缺点
    • 使用场景
  • 模式扩展
    • Computer
    • Client
    • 创建者模式对比
      • 工厂方法模式VS建造者模式
      • 抽象工厂模式VS建造者模式
  • 总结

概述

  • 建造者模式又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同属性的对象
  • 建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,不需要知道内部的具体构建细节(如用户在选购汽车的时候,只需要选择好方向盘、轮胎、发动机类型,不需要知道零件是怎么制造出来的)
  • 在这里插入图片描述
    例如需要把这些的配件组装成一个主机。第一步安装CPU、第二步安装风扇、第三步安装内存条…
    建造者模式注重于组装。

需求

创建共享单车

生产自行车是一个复杂的过程,它包含了车架,车座等组件的生产。而车架又有碳纤维,铝合金等材质的,车座有橡胶,真皮等材质。对于自行车的生产就可以使用建造者模式。

这里Bike是产品,包含车架,车座等组件;Builder是抽象建造者,MobikeBuilder和OfoBuilder是具体的建造者;Director是指挥者。类图如下:

需求类图

实例

Bike

package com.lx.design.creator.builder;

/**
 * TODO 添加描述
 *
 * @author lx
 * @date 2024/6/18 23:11
 * 自行车类
 */
public class Bike {
    private String frame;
    private String seat;

    public String getFrame() {
        return frame;
    }

    public void setFrame(String frame) {
        this.frame = frame;
    }

    public String getSeat() {
        return seat;
    }

    public void setSeat(String seat) {
        this.seat = seat;
    }
}

Builder

package com.lx.design.creator.builder;

/**
 * TODO 添加描述
 *
 * @author lx
 * @date 2024/6/18 23:12
 */
public abstract class Builder {
    protected Bike bike = new Bike();

    public abstract void buildFrame();
    public abstract void buildSeat();
    public abstract Bike createBike();
}


MobikeBuilder

package com.lx.design.creator.builder;

/**
* TODO 添加描述
*
* @author lx
* @date 2024/6/18 23:13
* 摩拜单车
*/
public class MobikeBuilder extends Builder {
   @Override
   public void buildFrame() {
       bike.setFrame("铝合金车架");
   }

   @Override
   public void buildSeat() {
       bike.setSeat("真皮车座");
   }

   @Override
   public Bike createBike() {
       return bike;
   }
}

OfoBuilder

package com.lx.design.creator.builder;

/**
* TODO 添加描述
*
* @author lx
* @date 2024/6/18 23:13
*/
public class OfoBuilder extends Builder{
   @Override
   public void buildFrame() {
       bike.setFrame("碳纤维车架");
   }

   @Override
   public void buildSeat() {
       bike.setSeat("橡胶车座");
   }

   @Override
   public Bike createBike() {
       return bike;
   }
}

Director

package com.lx.design.creator.builder;

/**
* TODO 添加描述
*
* @author lx
* @date 2024/6/18 23:15
*/
public class Director {
   private Builder mBuilder;

   public Director(Builder builder) {
       mBuilder = builder;
   }

   public Bike construct() {
       mBuilder.buildFrame();
       mBuilder.buildSeat();
       return mBuilder.createBike();
   }
}

Client

package com.lx.design.creator.builder;

/**
* TODO 添加描述
*
* @author lx
* @date 2024/6/18 23:16
*/
public class Client {
  public static void main(String[] args) {
      //创建建造者
      MobikeBuilder mobikeBuilder = new MobikeBuilder();
      //复制建造者
      Director director = new Director(mobikeBuilder);

      //建造者构建自行车
      Bike bike = director.construct();
      System.out.println(bike.getFrame());
      System.out.println(bike.getSeat());
  }
 
}

注意:

上面示例是 Builder模式的常规用法,指挥者类 Director 在建造者模式中具有很重要的作用,它用于指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类,但是有些情况下需要简化系统结构,可以把指挥者类和抽象建造者进行结合

// 抽象 builder 类
public abstract class Builder {

    protected Bike mBike = new Bike();

    public abstract void buildFrame();
    public abstract void buildSeat();
    public abstract Bike createBike();
    
    //添加以下代码
    public Bike construct() {
        this.buildFrame();
        this.BuildSeat();
        return this.createBike();
    }
}

Client

public static void main(String[] args) {
        Bike bike = new MobikeBuilder().construct();
        System.out.println(bike.getFrame());
         System.out.println(bike.getSeat());
    }

优缺点

优点:

  • 建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在指挥者类中对整体而言可以取得比较好的稳定性。
  • 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
  • 建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。符合开闭原则。

缺点:

造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。

使用场景

建造者(Builder)模式创建的是复杂对象,其产品的各个部分经常面临着剧烈的变化,但将它们组合在一起的算法却相对稳定,所以它通常在以下场合使用。

  • 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。
  • 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。

模式扩展

建造者模式除了上面的用途外,在开发中还有一个常用的使用方式,就是当一个类构造器需要传入很多参数时,如果创建这个类的实例,代码可读性会非常差,而且很容易引入错误,此时就可以利用建造者模式进行重构。

Computer

package com.lx.design.creator.builder.three;

/**
 * TODO 添加描述
 *
 * @author lx
 * @date 2024/6/19 16:27
 */
public class Computer {
    private String cpu;
    private String wifi;


    // 私有构造方法,只能通过Builder来创建对象
    private Computer(ComputerBuilder builder) {
     this.cpu=   builder.cpu;
     this.wifi=   builder.wifi;

    }

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getWifi() {
        return wifi;
    }

    public void setWifi(String wifi) {
        this.wifi = wifi;
    }

    public static class ComputerBuilder {
        private String cpu;
        private String wifi;



        public String getCpu() {
            return cpu;
        }

        public ComputerBuilder setCpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        public String getWifi() {
            return wifi;
        }

        public ComputerBuilder setWifi(String wifi) {
            this.wifi = wifi;
            return this;
        }

        public Computer build(){

            return new Computer(this);
        }
    }
}

Client

package com.lx.design.creator.builder.three;

/**
 * TODO 添加描述
 *
 * @author lx
 * @date 2024/6/19 16:33
 */
public class Client {
    public static void main(String[] args) {
        Computer build = new Computer.ComputerBuilder().setCpu("cpu")
                .setWifi("wifi").build();

        System.out.println(build.getWifi());
        System.out.println(build.getCpu());
    }
}

创建者模式对比

工厂方法模式VS建造者模式

工厂方法模式注重的是整体对象的创建方式;而建造者模式注重的是部件构建的过程,意在通过一步一步地精确构造创建出一个复杂的对象。

我们举个简单例子来说明两者的差异,如要制造一个超人,如果使用工厂方法模式,直接产生出来的就是一个力大无穷、能够飞翔、内裤外穿的超人;而如果使用建造者模式,则需要组装手、头、脚、躯干等部分,然后再把内裤外穿,于是一个超人就诞生了。建造者注重于步骤、组装。工厂方法注重于结果。

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

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

建造者模式则是要求按照指定的组件或者步骤建造产品,它的主要目的是通过组装零配件而产生一个新产品

如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车

总结

优点:

分步构建对象:

  • 建造者模式允许你按照步骤构建对象,通过链式调用或者在每个步骤中设置属性来完成。这样的方式比直接构造器构建更加灵活和直观,特别是当对象的构建过程比较复杂或者有多个可选参数时,尤为有效。

隐藏复杂构建过程:

  • 建造者模式将复杂对象的构建过程封装在一个独立的建造者类中,使得客户端代码不必知道具体的构建细节。客户端只需指定需要的配置和选项,而无需关心对象是如何一步步构建的。

提高代码复用性:

  • 可以通过建造者模式构建不同配置的对象,从而提高代码的复用性。同一个建造者可以用于构建多个不同表现形式的对象,只需改变建造者的配置参数即可。

便于控制构建过程:

  • 建造者模式可以在构建过程中逐步验证和设置对象的属性,可以在每个步骤中进行逻辑处理或者条件判断,从而更好地控制对象的构建过程。
    遵循单一职责原则:
  • 建造者模式将对象的构建和表示分离,每个具体建造者负责构建特定类型的对象。这有助于遵循单一职责原则,每个类专注于一个特定的构建任务。

缺点
增加了代码量:

  • 引入建造者模式会增加代码量,因为需要创建一个具体建造者类、可能的多个产品类以及指挥者(如果有的话)。这在简单对象的情况下可能显得繁琐。

对象构建过程更加复杂:

  • 如果对象相对简单,并且构建过程不太可能变化,使用建造者模式可能会显得过于复杂和冗余。此时直接使用构造函数或者工厂方法可能更为简单和直接。

不易于应对分步构建的变化:

  • 如果需要频繁修改对象的构建过程或者构建步骤,建造者模式可能会变得笨重,因为每次改动都需要修改建造者的逻辑或者添加新的建造者类。

可能导致对象不一致:

  • 如果在构建过程中缺少必要的约束或者验证逻辑,可能会导致最终构建的对象不符合预期,尤其是当对象的构建过程涉及多个步骤和条件时。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1851482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

threejs视频融合 webgl

threejs三维视频融合 let objList []; const clock new THREE.Clock(); const container document.getElementById( container );const stats new Stats(); container.appendChild( stats.dom );const renderer new THREE.WebGLRenderer( { antialias: true } ); rendere…

Day1:二分查找704 移除元素27

题目链接704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; int search(vector<int>& nums, int target) {int left 0;int right nums.size() - 1;int mid (right - left) / 2;while (left < right){if (target nums[mid]){return mid;}else if (target …

代码阅读器--Understand

代码阅读器--Understand 1 介绍2 安装步骤2.1 下载连接2.2 正常安装&#xff0c;设置自己的安装路径2.3 修改 understand.exe&#xff0c;搜索"areYouThere" &#xff0c; 用"IamNotHere!" 替代2.4 字节序替换 3 使用参考 1 介绍 Understand 的强大不言而…

用于制作耳机壳的UV树脂耳机壳UV胶价格高不高?

用于制作耳机壳的UV树脂耳机壳UV胶价格高不高&#xff1f; 制作耳机壳的UV树脂价格相对于一些其他材料可能会略高&#xff0c;但具体的价格取决于多个因素&#xff0c;如品牌、型号、质量等。一些高端的UV树脂品牌和型号可能会价格较高&#xff0c;但它们也通常具有更好的性能…

无法打开微软商店

今天给大家讲一下我在使用win11系统时遇到的一些问题&#xff0c;希望对出现类似情况的人有所帮助。 首先就是微软商店打不开的问题。相信许多windows系统的用户都会碰到此问题。我在打开时会出 现一直转圈的界面&#xff0c;在网上找了一些方法&#xff0c;但都没什么用处。…

提前还贷有“坑”?房产抵押经营贷避坑指南(十六大常见问题)

一、自己去银行还是找专人办理&#xff1f; 贷款这事儿&#xff0c;说起来容易&#xff0c;办起来可不简单。银行的大门敞开&#xff0c;但门槛却不低。很多人觉得自己资质不错&#xff0c;结果一申请才发现&#xff0c;条件这儿那儿都不符合&#xff0c;最后搞得心力交瘁&…

聚类算法(2)--- ISODATA算法

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在AI学习笔记&#…

【金】02Y90-60 大数据-HivetoMysQL

1、安装 Java 程序&#xff08;jdk&#xff09; 2、添加以下JAR包 3、确认配置成自己的数据库 ....

程序员为什么不能一次性写好,需要一直改Bug?

程序员在编写代码时不能一次性写好&#xff0c;而是需要不断修改Bug&#xff0c;这主要是由几个因素导致的&#xff1a; 复杂性&#xff1a;软件开发是一个高度复杂的过程&#xff0c;涉及到多个模块、功能、逻辑和数据的交互。即使是最有经验的程序员&#xff0c;也很难一次性…

[最新教程]Claude Sonnet 3.5注册方法详细步骤分享,新手小白收藏,文末免费送已注册的Claude账号

一.Claude sonnet 3.5大模型面世 6月21日&#xff0c;被称为“OpenAI 最强竞对”的大模型公司 Anthropic 发布了 Claude 3.5 系列模型中的第一个版本——Claude 3.5 Sonnet。 Anthropic 在官方博客中表示&#xff0c;Claude 3.5 Sonnet 提高了智能化的行业标准&#xff0c;在…

24年安克创新社招入职自适应能力cata测评真题分享北森测评高频题库

第一部分&#xff1a;安克创新自适应能力cata测评 感谢您关注安克创新社会招聘&#xff0c;期待与您一起弘扬中国智造之美。 为对您做出全面的评估&#xff0c;现诚邀您参加我们的在线测评。 测评名称&#xff1a;社招-安克创新自适应能力cata测评 第二部分&#xff1a;安克…

程序猿大战Python——面向对象——继承基础

定义类的几种语法 目标&#xff1a;了解定义类的标准语法。 我们知道&#xff0c;可以使用class关键字定义类。 在类的使用中&#xff0c;定义方式有三种&#xff1a; &#xff08;1&#xff09;【类名】 &#xff08;2&#xff09;【类名()】 &#xff08;3&#xff09;【…

【C++实验】多项式加减

题目&#xff1a;一元多项式运算 基本要求&#xff1a; &#xff08;1&#xff09; 输入并建立多项式; &#xff08;2&#xff09; 输出多项式; &#xff08;3&#xff09; 多项式加法 &#xff08;4&#xff09; 多项式减法。 测试数据&#xff1a; 代码展示&#xff1a; #i…

MarkDown基础

一、MarkDown标题 1.使用和-表示一级标题 2.使用#、##、###、####、######、######表示一级至六级标题 一级标题 二级标题 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 二、MarkDown标题 1.Markdown 段落没有特殊的格式&#xff0c;直接编写文字就好&#xff0c;…

全网最全!25届最近5年上海理工大学自动化考研院校分析

上海理工大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近5年考研分数情况 四、近5年招生录取情况 五、最新一年分数段图表 六、历年真题PDF 七、初试大纲复试大纲 八、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、考试…

【Linux系统】多线程

本篇博客继上一篇《线程与线程控制》&#xff0c;又整理了多线程相关的线程安全问题、互斥与锁、同步与条件变量、生产消费模型、线程池等内容&#xff0c;旨在让读者更加深刻地理解线程和初步掌握多线程编程。&#xff08;欲知线程的相关概念、线程控制的相关接口等&#xff0…

Ansible 自动化运维实践

随着 IT 基础设施的复杂性不断增加&#xff0c;手动运维已无法满足现代企业对高效、可靠的 IT 运维需求。Ansible 作为一款开源的自动化运维工具&#xff0c;通过简洁易用的 YAML 语法和无代理&#xff08;agentless&#xff09;架构&#xff0c;极大简化了系统配置管理、应用部…

Depth Anything V2:抖音开源高性能任何单目图像深度估计V2版本,并开放具有精确注释和多样化场景的多功能评估基准

&#x1f4dc;文献卡 题目&#xff1a; Depth Anything V2作者: Lihe Yang; Bingyi Kang; Zilong Huang; Zhen Zhao; Xiaogang Xu; Jiashi Feng; Hengshuang ZhaoDOI: 10.48550/arXiv.2406.09414摘要: This work presents Depth Anything V2. Without pursuing fancy technique…

前端 JS 经典:通用性函数封装思路

前言&#xff1a;设计通用性函数&#xff0c;我们需要考虑两个方面&#xff0c;一个是函数传参的可能性&#xff0c;如果可能性很多&#xff0c;我们可以将处理参数的方法暴露出去&#xff0c;让使用者去设计。为了调用的方便性&#xff0c;我们还可以做参数的归一化。 举个例…

计算机组成原理笔记-第3章 系统总线

第三章 系统总线 笔记PDF版本已上传至Github个人仓库&#xff1a;CourseNotes&#xff0c;欢迎fork和star&#xff0c;拥抱开源&#xff0c;一起完善。 该笔记是最初是没打算发网上的&#xff0c;所以很多地方都为了自我阅读方便&#xff0c;我理解了的地方就少有解释&#xf…