首页 > 其他分享 >07.生成器模式(Builder)

07.生成器模式(Builder)

时间:2023-06-26 10:46:21浏览次数:33  
标签:07 对象 Builder 生成器 模式 构建 public

使用生成器模式来解决问题

定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

生成器模式的结构和说明

  • Builder:生成器接口,定义创建一个 Product 对象所需的各个部件的操作。
  • ConcreteBuilder:具体的生成器实现,实现各个部件的创建,并负责组装 Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法。
  • Director:指导者,也被称为导向者,主要用来使用 Builder 接口,以一个统一的过程来构建所需要的 Product 对象。
  • Product:产品,表示被生成器构建的复杂对象,包含多个部件。

示例代码

namespace NetCore3Console.Builder
{
    /// <summary>
    /// 生成器接口,定义创建一个产品对象所需的各个部件的操作
    /// </summary>
    public interface IBuilder
    {
        /// <summary>
        /// 示意方法,构建某个部件
        /// </summary>
        void BuildPart();
    }

    /// <summary>
    /// 具体的生成器实现对象
    /// </summary>
    public class ConcreteBuilder : IBuilder
    {
        private IProduct resultProduct;

        public IProduct GetResult()
        {
            return resultProduct;
        }

        public void BuildPart()
        {
            //构建某个部件的功能处理
        }
    }

    /// <summary>
    /// 被构建的产品对象的接口
    /// </summary>
    public interface IProduct
    {
        //定义产品的操作
    }

    /// <summary>
    /// 指导者,指导使用生成器的接口来构建产品的对象
    /// </summary>
    public class Director
    {
        //持有当前需要使用的生成器对象
        private IBuilder _builder;

        //构造方法,传入生成器对象
        public Director(IBuilder builder)
        {
            _builder = builder;
        }

        //示意方法,指导生成器构建最终的产品对象
        public void Construct()
        {
            //通过使用生成器接口来构建最终的产品对象
            _builder.BuildPart();
        }
    }
}

认识生成器模式

生成式功能

生成器模式的主要功能是构建复杂的产品,而且是细化的、分步骤的构建产品,也就是生成器模式重在一步一步解决构造复杂对象的问题。

更为重要的是,这个构建的过程是统一的、固定不变的,变化的部分放到生成器部分了,只要配置不同的生成器,那么同样的构建过程,就能构建出不同的产品来。

生成器模式的重心在于分离构建算法和具体的构造实现,从而使得构建算法可以重用。具体的构造实现可以很方便地扩展和切换,从而可以灵活地组合来构造出不同的产品对象。

生成式的构成

  • 一个部分是 Builder 接口,这里是定义了如何构建各个部件,也就是知道每个部件功能如何实现,以及如何装配这些部件到产品中去;
  • 另外一个部分是 Director,Director 是知道如何组合来构建产品,也就是说 Director负责整体的构建算法,而且通常是分步骤地来执行。

不管如何变化,Builder 模式都存在这么两个部分一个部分是部件构造和产品装配另一个部分是整体构建的算法。

生成器模式的使用

应用生成器模式的时候,可以让客户端创造 Director,在 Director 里面封装整体构建算法,然后让 Director 去调用 Builder,让 Builder 来封装具体部件的构建功能,这就如同前面的例子。

使用生成器构建复杂对象

要想简洁直观、安全性好,又具有很好的扩展性地来创建这个对象的话,一个较好的选择就是使用 Builder 模式,把复杂的创建过程通过 Builder 来实现。

采用 Builder 模式来构建复杂的对象,通常会对 Builder 模式进行一定的简化,因为目标明确,就是创建某个复杂对象,因此做适当简化会使程序更简洁。大致简化如下:

  • 由于是用 Builder 模式来创建某个对象,因此就没有必要再定义一个 Builder 接口,直接提供一个具体的构建器类就可以了。
  • 对于创建一个复杂的对象,可能会有很多种不同的选择和步骤,干脆去掉“指导者”,把指导者的功能和 Client 的功能合并起来,也就是说,Client 这个时候就相当于指导者,它来指导构建器类去构建需要的复杂对象。
namespace NetCore3Console.Builder1
{
    /// <summary>
    /// 保险合同的对象
    /// </summary>
    public class InsuranceContract
    {
        //保险合同编号
        private string contractId;
        //被保险人的名称
        private string personName;
        //宝箱公司名称
        private string companyName;
        //保险开始生效日期
        private long beginDate;
        //失效日期
        private long endDate;
        //示例:其他数据
        private string otherData;

        public InsuranceContract(ConcreteBuilder builder)
        {
            contractId = builder.ContractId;
            personName = builder.PersonName;
            companyName = builder.CompanyName;
            beginDate = builder.BeginDate;
            endDate = builder.EndDate;
            otherData = builder.OtherData;
        }

        /// <summary>
        /// 示意:保险合同的某些操作
        /// </summary>
        public void SomeOperation()
        {
            //一些基础操作
        }
    }

    /// <summary>
    /// 构造保险合同对象的构建器
    /// </summary>
    public class ConcreteBuilder
    {
        public string ContractId { get;  }
        public string PersonName { get; set; }
        public string CompanyName { get; set; }
        public long BeginDate { get; }
        public long EndDate { get; }
        public string OtherData { get; set; }

        /// <summary>
        /// 构造方法,传入必须要有的参数
        /// </summary>
        /// <param name="contractId"></param>
        /// <param name="beginDate"></param>
        /// <param name="endDate"></param>
        public ConcreteBuilder(string contractId,long beginDate,long endDate)
        {
            ContractId = contractId;
            BeginDate = beginDate;
            EndDate = endDate;
        }
        /// <summary>
        /// 选填数据,被保险人员的名称
        /// </summary>
        /// <param name="personName"></param>
        /// <returns></returns>
        public ConcreteBuilder SetPersonName(string personName)
        {
            PersonName = personName;
            return this;
        }

        public ConcreteBuilder SetCompanyName(string companyName)
        {
            CompanyName = companyName;
            return this;
        }

        public ConcreteBuilder SetOtherData(string otherData)
        {
            OtherData = otherData;
            return this;
        }

        /// <summary>
        /// 构建方法
        /// </summary>
        /// <returns></returns>
        public InsuranceContract Build()
        {
            return new InsuranceContract(this);
        }
    }
}

生成器模式的优点

  • 松散耦合
    生成器模式可以用同一个构建算法构建出表现上完全不同的产品,实现产品构建和产品表现上的分离。生成器模式正是把产品构建的过程独立出来,使它和具体产品的表现松散耦合,从而使得构建算法可以复用,而具体产品表现也可以灵活地、方便地扩展和切换。
  • 可以很容易地改变产品的内部表示
    在生成器模式中,由于Builder 对象只是提供接口给 Director 使用,那么具体的部件创建和装配方式是被 Builder 接口隐藏了的,Director 并不知道这些具体的实现细节。这样一来,要想改变产品的内部表示,只需要切换 Builder 的具体实现即可,不用管 Director,因此变得很容易。
  • 更好的复用性
    生成器模式很好地实现了构建算法和具体产品实现的分离。这样一来,使得构建产品的算法可以复用。同样的道理,具体产品的实现也可以复用,同一个产品的实现,可以配合不同的构建算法使用。

思考生成器模式

生成器模式的本质:分离整体构建算法和部件构造。

生成器模式的重心还是在于分离整体构建算法和部件构造,而分步骤构建对象不过是整体构建算法的一个简单表现,或者说是一个附带产物。

何时选用生成器模式

  • 如果创建对象的算法,应该独立于该对象的组成部分以及它们的装配方式时。
  • 如果同一个构建过程有着不同的表示时。

标签:07,对象,Builder,生成器,模式,构建,public
From: https://www.cnblogs.com/huiteresa/p/17504700.html

相关文章

  • AtCoder Beginner Contest 307 ABCDE
    AtCoderBeginnerContest307A-WeeklyRecordsProblemStatement题意:告诉你有几个礼拜,问你每个礼拜走的路程和。Solution思路:按题意模拟,每7天加起来就行。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;intmain(){ intn; cin>>n; llsum=......
  • Linux多线程07-线程属性
    线程属性类型:pthread_attr_t描述:pthread_attr_setdetachstate()函数将由attr引用的线程属性对象的分离状态属性设置为detachstate中指定的值。分离状态属性确定使用线程属性对象attr创建的线程将在可连接状态还是分离状态下创建。可以在detachstate中指定以下值:P......
  • 07前后端项目上传gitee,后端多方式登录接口,发送短信功能,发送短信封装,短信验证码接口,短
    1前后端项目上传到gitee#公司里: -前端一个仓库---》一个团队-后端一个仓库---》一个团队-微服务:两三个人一个服务---》一个项目一个仓库-网上开源软件,前后端都在一起#在远端建立前端仓库#本地代码提交到远成仓库2后端多方式......
  • 迭代器和生成器
    根据许多平台(例如GitHub),JavaScript是目前最流行的编程语言。然而,流行就等于是最先进或最受喜爱的语言吗?它缺少某些被认为是其他语言不可或缺的组成部分的结构,例如广泛的标准库、不变性和宏。但在我看来,有一个细节没有得到足够的重视——发电机。在本文中,我想解释迭代器和生成器的......
  • ASM disk group mount fails with ORA-15036: disk is truncated [ID 1077175.1]
     ASMdiskgroupmountfailswithORA-15036:diskistruncated[ID1077175.1]--------------------------------------------------------------------------------  修改时间05-OCT-2011    类型PROBLEM    状态PUBLISHED  InthisDocument Sympto......
  • 1207. 独一无二的出现次数
    给你一个整数数组arr,请你帮忙统计数组中每个数的出现次数。如果每个数的出现次数都是独一无二的,就返回true;否则返回false。示例1:输入:arr=[1,2,2,1,1,3]输出:true解释:在该数组中,1出现了3次,2出现了2次,3只出现了1次。没有两个数的出现次数相同。>代码class......
  • “800703fa 尝试对注册表项执行非法操作”错误
    “800703fa尝试对注册表项执行非法操作”错误原因管理员使用服务帐户登录到服务器进行交互式会话,然后注销后,通常会发生此问题。例如,管理员可以使用服务器场帐户登录到Web前端(WFE)服务器,然后注销。此活动强制在该帐户的配置文件中卸载注册表项。这种情况使密钥无法供将来使......
  • Wallys/wifi 6 router ipq8072 enterprise wireless dual band /support wifi6e card.
    DR8072V01isanetworkingrouterpcbabasedonQualcommIPQ8072Acommunicationprocessor,withtwo10GbEinterfaces,onethroughanSFPcageandtheotherthroughanRJ45connector,plusfourGigabitEthernetports,and4×4MIMOWiFi6connectivity.Bas......
  • LOJ#6077. 「2017 山东一轮集训 Day7」逆序对题解
    考虑朴素dp,令\(f_{i,j}\)为\(1\simi\)排列有\(j\)个逆序对的排列数。有转移方程:\[f_{i,j}=\sum_{k=0}^{i-1}f_{i-1,j-k}\]特殊地,我们定义\(j<0\)的\(f_{i,j}\)为\(0\)。定义\(\displaystyleF_i(x)=\sum_{j=0}^{\infty}f_{i,j}x^j\),有\(\displaystyleF_{i}(x)=......
  • 服务器日志事件ID4107
    在查看系统日志时,你是否有遇到过事件ID4107错误,来源CAPI2,详细信息在<http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/authrootstl.cab>从自动更新cab中提取第三方的根目录列表失败,错误为:已处理证书链,但是在不受信任提供程序信任的根证书中终......