建造者模式

2023-05-16

建造者模式

◆建造者模式也属于创建型模式,它提供了一种创建对象的最佳方式。
◆定义: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
◆主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
◆用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建复杂对象(把内部的建造过程和细
节隐藏起来)
◆例子:

  • 工厂(建造者模式) :负责制造汽车(组装过>程和细节在工厂内)
  • 汽车购买者(用户) :你只需要说出你需要的>型号(对象的类型和内容),然后直接购买就可以使用了(不需要知道汽车是怎么组装的(车轮、 车门、>发动机、方向盘等等) )
    在这里插入图片描述
    建造者模式的四个角色
  1. Product(产品角色): 一个具体的产品对象。
  2. Builder(抽象建造者): 创建一个Product对象的各个部件指定的 接口/抽象类。
  3. ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。
  4. Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。指挥者指挥我们的具体的建造者来完成我们的产品

例一:


//指挥:核心,负责指挥建造一个工程,工程如何建造有它决定
public class Director {

    //指挥工人按顺序建房子
    public Product build(Builder builder){
          builder.buildA();
          builder.buildB();
          builder.buildC();
          builder.buildD();
          return builder.getProduct();
    }

}

//抽象的建造者:方法
public abstract class Builder {
    abstract void buildA();//地基
    abstract void buildB();//钢筋工程
    abstract void buildC();//铺电线
    abstract void buildD();//粉刷

    //完工:得到产品
    abstract Product getProduct();

}


//具体建造者:工人
public class Worker extends Builder{
    private Product product;
    public Worker(){
        product = new Product();
    }
    @Override
    void buildA() {
      product.setBuildA("建地基");
        System.out.println("建地基");
    }
    @Override
    void buildB() {
        product.setBuildB("钢筋工程");
        System.out.println("钢筋工程");
    }
    @Override
    void buildC() {
        product.setBuildC("铺电线");
        System.out.println("铺电线");
    }
    @Override
    void buildD() {
        product.setBuildD("粉刷");
        System.out.println("粉刷");
    }
    @Override
    Product getProduct() {
        return product;
    }
}
//产品:房子
public class Product {
    private String buildA;
    private String buildB;
    private String buildC;
    private String buildD;

    public String getBuildA() { return buildA; }
    public void setBuildA(String buildA) { this.buildA = buildA; }
    public String getBuildB() { return buildB; }
    public void setBuildB(String buildB) { this.buildB = buildB; }
    public String getBuildC() { return buildC; }
    public void setBuildC(String buildC) { this.buildC = buildC; }
    public String getBuildD() { return buildD; }
    public void setBuildD(String buildD) { this.buildD = buildD; }
}

public class Test {
    public static void main(String[] args) {
        //指挥
        Director director = new Director();

        //z指挥具体的工人完成产品
        Product build = director.build(new Worker());
        System.out.println(build.toString());
    }
}

例二
在这里插入图片描述

代码如下:

public class
BuilderPatternDemo1 {

    public static void main(String[] args) {

        //盖普通房子
        CommonHouse commonHouse = new CommonHouse();
        //准备创建房子的指挥者
        HouseDirector houseDirector = new HouseDirector(commonHouse);

        //完成盖房子,返回产品(普通房子)
        House house = houseDirector.constructHouse();

        //System.out.println("输出流程");

        System.out.println("--------------------------");
        //盖高楼
        HighBuilding highBuilding = new HighBuilding();
        //重置建造者
        houseDirector.setHouseBuilder(highBuilding);
        //完成盖房子,返回产品(高楼)
        houseDirector.constructHouse();



    }
}

/**
 * 产品
 */
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;
    }

}

// 抽象的建造者
abstract class HouseBuilder {

    protected House house = new House();

    //将建造的流程写好, 抽象的方法
    public abstract void buildBasic();
    public abstract void buildWalls();
    public abstract void roofed();

    //建造房子好, 将产品(房子) 返回
    public House buildHouse() {
        return house;
    }

}

class CommonHouse extends HouseBuilder {

    @Override
    public void buildBasic() {
        // TODO Auto-generated method stub
        System.out.println(" 普通房子打地基5米 ");
    }

    @Override
    public void buildWalls() {
        // TODO Auto-generated method stub
        System.out.println(" 普通房子砌墙10cm ");
    }

    @Override
    public void roofed() {
        // TODO Auto-generated method stub
        System.out.println(" 普通房子屋顶 ");
    }

}

class HighBuilding extends HouseBuilder {

    @Override
    public void buildBasic() {
        // TODO Auto-generated method stub
        System.out.println(" 高楼的打地基100米 ");
    }

    @Override
    public void buildWalls() {
        // TODO Auto-generated method stub
        System.out.println(" 高楼的砌墙20cm ");
    }

    @Override
    public void roofed() {
        // TODO Auto-generated method stub
        System.out.println(" 高楼的透明屋顶 ");
    }

}


//指挥者,这里去指定制作流程,返回产品
class HouseDirector {

    HouseBuilder houseBuilder = null;

    //构造器传入 houseBuilder
    public HouseDirector(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    //通过setter 传入 houseBuilder
    public void setHouseBuilder(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    //如何处理建造房子的流程,交给指挥者
    public House constructHouse() {
        houseBuilder.buildBasic();
        houseBuilder.buildWalls();
        houseBuilder.roofed();
        return houseBuilder.buildHouse();
    }


}

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

通过静态内部类方式实现零件无序装配构造,这种方式使用更加灵活,更符合定义。内部有复杂对象的默认实现,使用时可以根据用户需求自由定义更改内容,并且无需改变具体的构造方式。就可以生产出不同复杂产品

比如:比如麦当劳的套餐,服务员(具体建造者)可以随意搭配任意几种产品(零件)组成一款套餐(产品),然后出售给客户。比第一种方式少 了指挥者,主要是因为第二种方式把指挥者交给用户来操作,使得产品的创建更加简单灵活。

例三: 没有指挥者参与

//建造者
public abstract class Builder {
    abstract Builder buildA(String msg); //汉堡
    abstract Builder buildB(String msg); //可乐
    abstract Builder buildC(String msg); //薯条
    abstract Builder buildD(String msg); //甜点

    abstract Product getProduct();
}

public class Worker extends Builder{
    private Product product;

    public Worker(){ product = new Product(); }
    @Override
    Builder buildA(String msg) {
        product.setBuildA(msg);
        return this;
    }
    @Override
    Builder buildB(String msg) {
        product.setBuildB(msg);
        return this;
    }
    @Override
    Builder buildC(String msg) {
        product.setBuildC(msg);
        return this;
    }
    @Override
    Builder buildD(String msg) {
        product.setBuildD(msg);
        return this;
    }
    @Override
    Product getProduct() {
        return product;
    }
}

//产品:套餐
public class Product {
    private String BuildA = "汉堡";
    private String BuildB = "可乐";
    private String BuildC = "薯条";
    private String BuildD = "甜点";

    public String getBuildA() { return BuildA; }
    public void setBuildA(String buildA) { BuildA = buildA; }
    public String getBuildB() { return BuildB; }
    public void setBuildB(String buildB) { BuildB = buildB; }
    public String getBuildC() { return BuildC; }
    public void setBuildC(String buildC) { BuildC = buildC; }
    public String getBuildD() { return BuildD; }
    public void setBuildD(String buildD) { BuildD = buildD; }
    @Override
    public String toString() {
        return "Product{" +
                "BuildA='" + BuildA + '\'' +
                ", BuildB='" + BuildB + '\'' +
                ", BuildC='" + BuildC + '\'' +
                ", BuildD='" + BuildD + '\'' +
                '}';
    }
}

public class Test {
    public static void main(String[] args) {
        //服务员
        Worker worker = new Worker();
        //Product product = worker.getProduct();
       // System.out.println(product.toString());
        //链式编程 :在原来基础上可以自由组合
        Product product = worker.buildA("鸡肉卷").buildB("橘子汽水").getProduct();
        System.out.println(product.toString());
    }
}

例四:
在这里插入图片描述

import java.util.ArrayList;
import java.util.List;

/**
 * @anthor longzx
 * @create 2021 03 15 22:45
 * @Description
 **/
public class BuilderPatternDemo2 {
    public static void main(String[] args) {
        MealBuilder mealBuilder = new MealBuilder();

        Meal vegMeal = mealBuilder.prepareVegMeal();
        System.out.println("Veg Meal");
        vegMeal.showItems();
        System.out.println("Total Cost: " +vegMeal.getCost());

        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        System.out.println("\n\nNon-Veg Meal");
        nonVegMeal.showItems();
        System.out.println("Total Cost: " +nonVegMeal.getCost());
    }

}

interface Item {
    public String name();
    public Packing packing();
    public float price();
}

interface Packing {
    public String pack();
}

class Wrapper implements Packing {

    @Override
    public String pack() {
        return "Wrapper";
    }
}

class Bottle implements Packing {

    @Override
    public String pack() {
        return "Bottle";
    }
}

abstract class Burger implements Item {

    @Override
    public Packing packing() {
        return new Wrapper();
    }

    @Override
    public abstract float price();
}

abstract class ColdDrink implements Item {

    @Override
    public Packing packing() {
        return new Bottle();
    }

    @Override
    public abstract float price();
}
class VegBurger extends Burger {

    @Override
    public float price() {
        return 25.0f;
    }

    @Override
    public String name() {
        return "Veg Burger";
    }
}
class ChickenBurger extends Burger {

    @Override
    public float price() {
        return 50.5f;
    }

    @Override
    public String name() {
        return "Chicken Burger";
    }
}
class Coke extends ColdDrink {

    @Override
    public float price() {
        return 30.0f;
    }

    @Override
    public String name() {
        return "Coke";
    }
}
class Pepsi extends ColdDrink {

    @Override
    public float price() {
        return 35.0f;
    }

    @Override
    public String name() {
        return "Pepsi";
    }
}

/**
 * 产品
 */
class Meal {
    private List<Item> items = new ArrayList<Item>();

    public void addItem(Item item){
        items.add(item);
    }

    public float getCost(){
        float cost = 0.0f;
        for (Item item : items) {
            cost += item.price();
        }
        return cost;
    }

    public void showItems(){
        for (Item item : items) {
            System.out.print("Item : "+item.name());
            System.out.print(", Packing : "+item.packing().pack());
            System.out.println(", Price : "+item.price());
        }
    }
}

class MealBuilder {

    public Meal prepareVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }

    public Meal prepareNonVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}

◆应用场景:

  • 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
  • 适合于一 个具有较多的零件(属性)的产品(对象)的创建过程。

◆建造者与抽象工厂模式的比较:

  • 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
  • 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象, 返回一个完整的对象。
  • 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回-一辆完整的汽车!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

建造者模式 的相关文章

  • tkinter多进程报错TypeError: cannot pickle ‘_tkinter.tkapp‘ object eof error ran out of input

    这是初始错误的代码 span class token keyword def span span class token function Convert span span class token punctuation span spa
  • Ubuntu 操作**.sh文件时 Permission denied 解决

    chmod u 43 x 43 文件名
  • 秒杀商品的一些思路分享,redis的链表、mq、mysql排他锁

    运用的技术 1 redis链表 xff08 预库存 xff09 2 rabbitMq xff08 记录秒杀成功的订单数据 xff09 3 php 两个方案 1 mysql 开启事务 xff0c 生成排他锁 x1f512 2 redis链表
  • 服务器配置https,以及报错解决

    一 获取SSL证书 1 1 阿里中购买SSL证书 1 二 安装SSL证书 2 1 下载证书 2 2 使用nginx配置 2 三 配置SSL证书 3 四 参考文档分享 4 开启HTTPS 获取SSL证书 阿里中购买SSL证书 1 登录到阿里云
  • 一款超好用的python的log记录工具——loguru

    一款超好用的python的log记录工具 loguru 1 安装 pip span class token function install span loguru 2 使用简介 2 1 add 函数 在loguru中 xff0c 只需要通
  • Eclipse控制台Console使用说明

    1 说明 本文详细介绍Eclipse控制台Console使用说明 xff0c 调试时通过控制台查看日志 xff0c 有时候日志太多会找不到上面的日志 xff0c 有时候几个控制台会不受控制的弹出 xff0c 那么请参考本文 xff0c 通过
  • 二叉树高度最简单的求法

    假设这是一颗满二叉树 xff0c n为节点的总个数 xff0c 那么 n 43 1 2为最后一层节点数 xff0c 除以h 1次的2就是第一层的节点数即为1 之所以选择满二叉树来算 xff0c 是因为这样算起来最方便 xff0c 最后一层节
  • 单片机类型介绍和入门单片机

    单片机类型介绍和入门单片机 单片机是一种集成电路芯片 xff0c 通常包含一个或多个中央处理器 xff08 CPU xff09 存储器 输入输出端口 xff08 I O xff09 和计时器等部件 xff0c 可以完成各种控制和数据处理任务
  • Python 3.7 安装完成后import ssl失败解决方法

    提示找不到SSL模块 python安装完毕后 xff0c 提示找不到ssl模块 xff1a root 64 localhost python2 7 5 Python 2 7 5 default Jun 3 2013 11 08 43 GCC
  • activemq的安装和使用【2】activemq的queue模式

    activemq共有两种模式 xff0c 一是点对点 xff0c 一是发布和订阅 xff0c 不管是哪种方式 xff0c 都包含两个角色 xff0c 一是消息的生产者 xff0c 一是消息的消费者 点对点是消息只能被一个消费者收到 xff0
  • Nacos源码分析

    Nacos源码分析 1 下载Nacos源码并运行 要研究Nacos源码自然不能用打包好的Nacos服务端jar包来运行 xff0c 需要下载源码自己编译来运行 1 1 下载Nacos源码 Nacos的GitHub地址 xff1a https
  • Sentinel源码分析

    Sentinel源码分析 1 Sentinel的基本概念 Sentinel实现限流 隔离 降级 熔断等功能 xff0c 本质要做的就是两件事情 xff1a 统计数据 xff1a 统计某个资源的访问数据 xff08 QPS RT等信息 xff
  • Nginx 基础使用、配置文件详解、Keepalived高可用

    Nginx 基础使用 安装 span class token comment 解压nginx压缩包 xff0c 压缩包自行下载 span tar zxvf nginx 1 span class token punctuation span
  • 阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义

    常用文件夹分层 xff1a pojo vo xff08 与前端交互的所有对象 xff0c 包括接参和返回 xff09 query xff08 查询的筛选条件 xff0c 前端传参和后端内部传参通用 xff09 entity xff08 数据
  • 分布式锁笔记

    分布式锁笔记 分布式锁1 传统锁回顾1 1 从减库存聊起1 2 环境准备1 3 简单实现减库存1 4 演示超卖现象1 5 jvm锁问题演示1 5 1 添加jvm锁1 5 2 原理 1 6 多服务问题1 6 1 安装配置nginx1 6 2
  • 分布式锁总结

    乐观锁 在select的时候不会加锁 xff0c 是基于程序实现的 xff0c 所以不会存在死锁的情况 适用于读多写少的场景 xff08 写的并发量相对不高 xff09 xff0c 可以提高系统的吞吐量 因为如果写多的话 xff0c 乐观锁
  • Xstart远程连接Linux图形用户界面

    目标 xff1a 在自己的Windows桌面打开Linux的firefox浏览器 工具 xff1a Windows Xmanager的Xstart工具 Linux xterm firefox 说明 xff1a 使用Xstart远程连接Lin
  • 微信内置小程序在线客服功能

    在小程序中加入客服消息按钮 小程序接入微信 客服消息 功能模块 xff0c 开发者只需要调用按钮 xff0c 触发微信的客服消息功能即可 xff0c 不需要自行在小程序中实现 加入客服消息按钮有两个方法 xff0c 大家可以根据自己的实际需
  • Java实例化泛型

    public D newUsr D newUsr try 通过反射获取model的真实类型 ParameterizedType pt 61 ParameterizedType this getClass getGenericSupercla
  • Windows桌面下面任务栏无法点击(卡住)的解决办法

    Windows桌面下面任务栏无法点击 卡住 的解决办法 大家再使用Windows的时候 xff0c 有时候会碰到桌面卡住无法点击下面的任何图标的现象 xff0c 若不知道如何解决 xff0c 可能就开始重启电脑了 xff0c 其实不必要 x

随机推荐

  • 剑指offer03

    数组中的重复数字 题目 在一个长度为 n 的数组 nums 里的所有数字都在 0 xff5e n 1 的范围内 数组中某些数字是重复的 xff0c 但不知道有几个数字重复了 xff0c 也不知道每个数字重复了几次 请找出数组中任意一个重复的
  • 如何pycharm与jupyter lab/notebook结合使用

    如何pycharm与jupyter lab notebook结合使用 原因效果教程 原因 jupyter lab的自动补全并不好用 xff0c 使用了kite后总是存在卡顿的现象 xff0c 正好在pycharm中支持jupyter lab
  • 【杭电100题】2073 无限的路

    题目链接 xff1a http acm hdu edu cn showproblem php pid 61 2073 xff08 c语言的double类型printf lf 显示0 00000问题 xff09 xff1a https blo
  • 【杭电100题】2094 产生冠军

    原题 xff1a http acm hdu edu cn showproblem php pid 61 2094 最近很喜欢用map 把成功者 失败者都存起来 然后在成功者里把曾经失败的划掉 最后成功者里如果只剩一个人 xff0c 冠军产生
  • 逆变电路

    逆变的概念 与整流相对应 xff0c 直流电 变成 交流电 交流侧接电网 xff0c 为 有源逆变 交流侧接负载 xff0c 为 无源逆变 xff0c 本章主要讲述无源逆变 逆变与变频 变频电路 xff1a 分为 交交变频 和 交直交变频
  • 博客搭建教程1-Archlinux环境配置

    文章目录 1 前言2 archlinux镜像下载3 archlinux安装 1 前言 这个教程主要讲解linux环境下博客的搭建 xff0c 这里的linux系统选择archlinux xff0c 博客的框架基于hexo框架 参考博客 xf
  • 如何在git bash中启用复制粘贴快捷键

    方法一 xff1a 1 鼠标右键点击左上角 xff0c 选择属性 xff08 如果是英文就选择properties xff09 xff1a 2 在选项中勾选相应选项 xff1a 然后就完事了 方法二 xff1a 从其他地方复制一段文本 2
  • 栈,队列(纸牌游戏,小猫钓鱼)

    文章目录 队列 xff1a FIFO实现顺序队列 xff1a 1 顺序循环队基本操作2 链队 栈1 顺序栈栈的元素初始化操作入栈操作判断顺序栈是否为空栈的长度出栈清空一个栈销毁顺序栈 2 链式栈 应用栈1 xff1a 判断回文字符串栈与队列
  • SELinux

    domain https www cnblogs com ly565911158 p 3622942 html coredomain https www cnblogs com liwugang p 12433028 html xff08
  • 电脑任务栏无法点击

    解决方法 1 启动任务管理器 xff08 Ctrl 43 alt 43 找到windows 资源管理器重新启动 xff09 2 win10 更新后右下方有个天气资讯的推送点击全部选择关闭 xff0c 在任务栏上也点击取消
  • 如何快速获取网页源码(直接把网站的 js css html 扒下来的)

    如何快速获取网页源码 xff1f 我们在学习和研究的时候 或者看到非常酷炫的页面效果 xff0c 需要网站的源代码进行借鉴 xff0c 但每次需要下载网站源代码 xff0c 我们都需要找到一个 xff0c 下载一个 xff0c 每次只能下载
  • 人工智能大作业——人脸识别系统(最终)

    写在前面 时间过得飞快 xff0c 时间已经距离我发第一篇文章过去2年多了 xff0c 也不再从事代码工作 xff0c 偶然间上到csdn翻看文章经过 xff0c 看到还是有些人关注人脸识别系统的后续的 xff0c 我猜大概率是学弟学妹们正
  • JAVA json 三种格式

    json三种格式 span class token class name JSONObject span jsonParam span class token operator 61 span span class token keywor
  • java.lang.NumberFormatException: For input string: ""解决方案

    引起异常的主要原因如下 xff1a 1 传参字段和映射字段不一致2 传参类型和映射类型不一致3 时间类型转换时间戳长度不一致4 参数长度和数据库不一致 Service 层代码 span class token keyword public
  • 个性化命令提示符CMD,不止简单地美化,Dos命令让你的命令提示符cmd花里胡哨

    自重温了下注册表知道了autorun子项后 我把cmd重新设计了一遍 先上图 win10系统 cmd版本为10 0 17763 1 原理 添加注册表命令行的自启动项 使启动cmd时会自动运行项的命令值 打开注册表 win R 输入reged
  • Pandas入门第二章之数据的读取

    本节主要介绍pandas经常读取的两种数据格式 xff0c 其分别是CSV和JSON本节使用两个数据集分别是2019腾讯算法大赛和中国AI创新创业大赛的数据集 没有标签的原始数据的格式 带标题的数据格式 本节在介绍pandas读取CSV文件
  • 使用Javascript 创建枚举类型(enum)

    使用Javascript 创建枚举类型 xff08 enum xff09 1 枚举类型的定义 是指将变量的值一一列出来 变量的值只限于列举出来的值的范围内 2 typescript中的枚举类型 span class token keywor
  • 一个七年Java女程序员的年终总结,写给过去一年的自己

    简单先说一下 xff0c 坐标杭州 xff0c 14届本科毕业 xff0c 算上年前在阿里巴巴B2B事业部的面试 xff0c 一共有面试了有6家公司 xff08 因为不想请假 xff0c 因此只是每个晚上去其他公司面试 xff0c 所以面试
  • HTML初识

    文章目录 思维导图HTML标签浏览器内核Web标准骨架标签VScode的使用网页开发工具解释标签图像标签注意点路径视频格式 xff08 后续会补充 xff09 链接 思维导图HTML标签 xff08 表示后面有相应解释 xff09 浏览器内
  • 建造者模式

    建造者模式 建造者模式也属于创建型模式 xff0c 它提供了一种创建对象的最佳方式 定义 将一个复杂对象的构建与它的表示分离 xff0c 使得同样的构建过程可以创建不同的表示 主要作用 在用户不知道对象的建造过程和细节的情况下就可以直接创建