创建型模式之建造者模式

326 阅读4分钟

(Builder Pattern)使用多个简单的对象一步一步创建成一个复杂的对象,属于创建性模式

介绍

意图: 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示

主要解决:在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构 成,由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定

何时使用:一些基本不会变,而其组合经常变化的时候

如何解决:将变与不变分离开

关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系

应用实例:去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"

优点:1. 建造者独立,易扩展 2.便于控制风险

缺点:1.产品必须有共同点,范围有限制 2.如内部变化复杂,会有很多的建造类

使用场景:1. 需要生成的对象具有复杂的内部结构 2.需要生成的对象内部属性本身相互依赖

注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

模式结构和说明

建造者(生成器)模式的结构如图所示: 在这里插入图片描述

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

场景

需求: 写一份资料,开头必须是标题,日期,中间部分文本,结尾写编辑者,联系方式等

这还不简单,一份word文档Ok,但客户看了发现不直观,没有一点格式性,何况看着也麻烦,你给我弄成个HTML文件吧,又整一份.如果这个客户是个程序员,我想来个macdown文件呢,烦躁,太麻烦了一个文件而已要那么多格式,老子不干了

从开发的角度来做这件事,就是需要导出一个文件,但文件的格式不定,这怎么弄呢?仔细分析上面的问题,导出的文件,不管是什么格式,都分成三个部分,头文件,文件体和文件尾

怎么实现上述功能呢?下面来撸代码

不用模式的解决方案

  • 首先定义文件头,文件体和文件尾
 HeaderModel: {
   String title,
   String date
 } 
 
 BodyModel:{
   string body
 }
 
 FooterModel:{
    string author
    string connact
 }
  • 编写word格式,HTMl格式
  class ExtportTxt{
    exportTxt(HeaderModel header, BodyModel body, FooterModel footer)
    {
        String  *txt = String()
        txt.append(header.title)
        txt.append(body.body)
        txt.append(footer.author) 
    }
  }
 
   class ExtportHtml{
    exportHtml(HeaderModel header, BodyModel body, FooterModel footer)
    {
        String  *txt = String()
        txt.append('<header>' +header.title+ '</header>')
        //下面的格式暂不写了
        txt.append(body.body)
        txt.append(footer.author) 
    }
  }

完美实现,但你会发现不论是什么格式,在实现的时候步骤基本是一样的,分为三步:

  1. 拼接头文件
  2. 拼接文件提
  3. 拼接文件尾

也就是说对于不同的输出格式,处理的步骤是一样的,但是每步的具体实现是不一样的,那咱们能不能把处理的步骤和具体的实现分开呢,这样就能复用处理过程

建造者模式来解决

定义:将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建出不同的表现

分析上面例子的实现,构建每种格式的数据文件的处理过程,不就是构建过程吗?而每种格式具体的步骤实现,不就是相当于不同的表示吗?因为不同步骤的实现,决定了最终的表现不同

要实现同样的构建过程可以创建不同的表现,那就把构建过程独立出来,在建造者模式中称为指导者,由它来完成指导装配过程,但不负责具体的实现.具体的实现对象在建造者模式中称为生成器

用模式来重写示例

  • 数据模型不变

  • 定义builder父类

 Class Builder {
    buildHeader(HeaderModel header)
    buildBody(BodyModel  body)
    buildFooter(FooterModel footer)
 }
  • 具体的生成器
 Class TxtBuilder:Builder {
   String result = String()
    buildHeader(HeaderModel header) {
        result.append(header.title)
        result.append(header.date)
    }
    buildBody(BodyModel  body){
       result.appen(body.body)
    }
    buildFooter(FooterModel footer){
     footer.append(footer.author)
    }
 }
  Class HTMLBuilder:Builder {
   String result = String()
    buildHeader(HeaderModel header) {
        result.append("<header>"+header.title+"</header>")
        result.append(header.date)
    }
    buildBody(BodyModel  body){
       result.appen("<body>"+body.body+"</body>")
    }
    buildFooter(FooterModel footer){
     footer.append(footer.author)
    }
 }
  • 指导者
  Class Director {
     Builder builder
     createProduct(HeaderModel header, BodyModel body, FooterModel footer){
        builder.builderHeader(header)
        builder. buildBody(header)
        builder. buildFooter(header)     
     }
  }

解释

指导者承担的是整体构建算法部分,是相对不变的部分,也就是说构建过程是不变的,变化的部分都放在了生成器中

本质

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

Demo地址