美文网首页
第十二章:构建模式

第十二章:构建模式

作者: Benedict清水 | 来源:发表于2022-07-15 21:53 被阅读0次

作为一个打工仔,在外面辛苦了一年,李力终于要回家过年了。李力给他的小侄子买了两套积木游戏玩具。小侄子玩的不亦乐乎,小侄子把四个轮子、一个车身、一个发动机和一个方向盘拼装成了一辆车。用一间客厅、两个卧室、一间书房、一间厨房、一个花园和一堵围墙搭建了一个庄园......

一、用代码来模拟生活

from abc import ABCMeta, abstractmethod


class Toy(metaclass=ABCMeta):
    """玩具"""

    def __init__(self, name):
        self._name = name
        self.__components = []

    def getName(self):
        return self._name

    def addComponent(self, component, count=1, unit="个"):
        self.__components.append([component, count, unit])
        print("%s 增加了 %d %s%s" % (self._name, count, unit, component))

    @abstractmethod
    def feature(self):
        pass


class Car(Toy):
    """小车"""

    def feature(self):
        print("我是%s, 我可以快速奔跑......" % self._name)


class Manor(Toy):
    """庄园"""

    def feature(self):
        print("我是%s, 我可供观赏。也可用来游玩!" % self._name)


class ToyBuilder:
    """玩具构建者"""

    def buildCar(self):
        car = Car("迷你小车")
        print("正在构建%s......" % car.getName())
        car.addComponent("轮子", 4)
        car.addComponent("车身", 1)
        car.addComponent("发动机", 1)
        car.addComponent("方向盘")
        return car

    def buildManor(self):
        manor = Manor("淘淘小庄园")
        print("正在构建 %s......" % manor.getName())
        manor.addComponent("客厅", 1, "间")
        manor.addComponent("卧室", 1, "间")
        manor.addComponent("书房", 1, "间")
        manor.addComponent("厨房", 1, "间")
        manor.addComponent("花园", 1, "个")
        manor.addComponent("围墙", 1, "堵")
        return manor


if __name__ == "__main__":
    builder = ToyBuilder()
    car = builder.buildCar()
    car.feature()
    print("\n")
    mannor = builder.buildManor()
    mannor.feature()

用golang来演示:

package main

import "fmt"

type component struct {
    name  string
    count int
    unit  string
}

type ToyInterface interface {
    getName() string
    addComponent(c component)
    feature()
}

type Toy struct {
    name       string
    components []component
}

func (t Toy) getName() string {
    return t.name
}

func (t Toy) addComponent(c component) {
    t.components = append(t.components, c)
    fmt.Printf("%s 增加了 %d %s %s \n", t.name, c.count, c.unit, c.name)
}

func (t Toy) feature() {
    fmt.Println("我是玩具......")
}

type Car struct {
    Toy
}

func (c Car) feature() {
    fmt.Printf("我是%s,我可以快速奔跑......\n", c.name)
}

type Manor struct {
    Toy
}

func (m Manor) feature() {
    fmt.Printf("我是%s,我可供欣赏,也可用来游玩!", m.name)
}

type ToyBuilder struct {
}

func (t ToyBuilder) buildCar() ToyInterface {
    car := Car{Toy{
        name:       "迷你小车",
        components: make([]component, 0, 10),
    }}
    fmt.Printf("正在构建%s......\n", car.getName())
    c1 := component{
        name:  "轮子",
        count: 4,
        unit:  "个",
    }
    car.addComponent(c1)
    c2 := component{
        name:  "车身",
        count: 1,
        unit:  "个",
    }
    car.addComponent(c2)
    c3 := component{
        name:  "发动机",
        count: 1,
        unit:  "个",
    }
    car.addComponent(c3)
    c4 := component{
        name:  "方向盘",
        count: 1,
        unit:  "个",
    }
    car.addComponent(c4)
    return car
}

func (t ToyBuilder) buildManor() ToyInterface {
    manor := Manor{Toy{
        name:       "淘淘小庄园",
        components: make([]component, 5, 10),
    }}
    fmt.Printf("正在构建%s......\n", manor.getName())
    c1 := component{
        name:  "客厅",
        count: 1,
        unit:  "间",
    }
    manor.addComponent(c1)
    c2 := component{
        name:  "卧室",
        count: 1,
        unit:  "间",
    }
    manor.addComponent(c2)
    c3 := component{
        name:  "书房",
        count: 1,
        unit:  "间",
    }
    manor.addComponent(c3)
    c4 := component{
        name:  "厨房",
        count: 1,
        unit:  "间",
    }
    manor.addComponent(c4)
    c5 := component{
        name:  "花园",
        count: 1,
        unit:  "个",
    }
    manor.addComponent(c5)
    c6 := component{
        name:  "围墙",
        count: 1,
        unit:  "堵",
    }
    manor.addComponent(c6)
    return manor
}

func main() {
    builder := ToyBuilder{}
    car := builder.buildCar()
    car.feature()
    fmt.Println()
    mannor := builder.buildManor()
    mannor.feature()
}

二、设计思想

构建顾名思义就是把各种部件通过一定的方式和流程构造成一个成品的过程。在程序中,我们将这一过程称为构建模式(英文叫Builder Pattern,不同的书籍和资料翻译各有不同,有的也叫建造者模式或生成器模式)。
构建模式的核心思想是:将产品的创建过程与产品本身分离开来,使得创建过程更加清晰,能够更加精确地控制复杂对象的创建过程,让使用者可以用相同的创建过程创建不同的产品。

三、比较

3.1 与工厂模式的区别

工厂模式关注的是整个产品(整体对象)的生成,即成品的生成;而构建模式关注的是产品的创建过程和细节,一步一步地由各个子部件构建为一个成品。
比如要创建一辆汽车,如果用工厂模式,直接就创建一辆有车身、轮胎、发动机的能用的汽车。如果用构建模式,则需要由车身、轮胎、发动机一步一步地组装成一辆汽车。

3.2与组合模式的区别

组合模式关注的是“整体-部分”的关系,也就是关注对象的内部组成结构,那么它与构建模式又有什么区别与联系呢?
区别:组合模式关注的是对象内部的组成结构,强调的是部分与整体的关系。构建模式关注的是对象的创建过程,即由一个一个的子部件构建一个成品的过程。
联系:组合模式和构建模式其实也经常被一起使用。还是以组装电脑为例,组合模式和构建模式一起使用。
组装电脑的时候,内存卡(Memory Card)、硬盘(Hard Disk)、核心处理器(CPU)、电池(Battery)、风扇(Fan)都是独立的电子元件,而主板(Mainboard)和机箱(Computer Case)都是由子元件组成的。我们的ComputerBuilder就是构建者,负责整个电脑的组装过程:先把内存卡、硬盘、“CPU组装在主板上,再把主板、电池、风扇组装在机箱里,最后连接鼠标、键盘、显示器,就构成了一台完整的台式电脑。

四、升级版

如果Toy不只有车(car)和庄园(Manor),还有飞机、坦克、摩天轮、过山车等,而且不只造一辆车和一个庄园,数量由用户自己定。那么builder就会变得越来越臃肿,那么就需要进行升级。 升级版构建模式的类图.png

Product是产品的抽象类(基类),ProductA和ProductB是具体的产品。Builder是抽象构建类,ProductABuilder和ProductBBuilder是对应产品的具体构建类,而BuilderManager是构建类的管理类(很多资料和书籍中叫它导演类(Director)),负责管理每一种产品的创建数量和创建顺序。

package main

import "fmt"

// 组件
type component struct {
    name  string
    count int
    unit  string
}

type ToyInterface interface {
    getName() string
    addComponent(c component)
    feature()
}

// Toy 玩具
type Toy struct {
    name       string
    components []component
}

func (t Toy) getName() string {
    return t.name
}

func (t Toy) addComponent(c component) {
    t.components = append(t.components, c)
    fmt.Printf("%s 增加了 %d %s %s \n", t.name, c.count, c.unit, c.name)
}

func (t Toy) feature() {
    fmt.Println("我是玩具......")
}

// Car 小车
type Car struct {
    Toy
}

func (c Car) feature() {
    fmt.Printf("我是%s,我可以快速奔跑......\n", c.name)
}

// Manor 庄园
type Manor struct {
    Toy
}

func (m Manor) feature() {
    fmt.Printf("我是%s,我可供欣赏,也可用来游玩!", m.name)
}

type ToyBuilderInterface interface {
    buildProduct() ToyInterface
}

// ToyBuilder 玩具构建者
type ToyBuilder struct {
}

func (t ToyBuilder) buildProduct() ToyInterface {
    return Toy{}
}

// CarBuilder 车的构建类
type CarBuilder struct {
    ToyBuilder
}

func (t CarBuilder) buildProduct() ToyInterface {
    car := Car{Toy{
        name:       "迷你小车",
        components: make([]component, 0, 10),
    }}
    fmt.Printf("正在构建%s......\n", car.getName())
    c1 := component{
        name:  "轮子",
        count: 4,
        unit:  "个",
    }
    car.addComponent(c1)
    c2 := component{
        name:  "车身",
        count: 1,
        unit:  "个",
    }
    car.addComponent(c2)
    c3 := component{
        name:  "发动机",
        count: 1,
        unit:  "个",
    }
    car.addComponent(c3)
    c4 := component{
        name:  "方向盘",
        count: 1,
        unit:  "个",
    }
    car.addComponent(c4)
    return car
}

// ManorBuilder 庄园的构建类
type ManorBuilder struct {
}

func (t ManorBuilder) buildProduct() ToyInterface {
    manor := Manor{Toy{
        name:       "淘淘小庄园",
        components: make([]component, 5, 10),
    }}
    fmt.Printf("正在构建%s......\n", manor.getName())
    c1 := component{
        name:  "客厅",
        count: 1,
        unit:  "间",
    }
    manor.addComponent(c1)
    c2 := component{
        name:  "卧室",
        count: 1,
        unit:  "间",
    }
    manor.addComponent(c2)
    c3 := component{
        name:  "书房",
        count: 1,
        unit:  "间",
    }
    manor.addComponent(c3)
    c4 := component{
        name:  "厨房",
        count: 1,
        unit:  "间",
    }
    manor.addComponent(c4)
    c5 := component{
        name:  "花园",
        count: 1,
        unit:  "个",
    }
    manor.addComponent(c5)
    c6 := component{
        name:  "围墙",
        count: 1,
        unit:  "堵",
    }
    manor.addComponent(c6)
    return manor
}

// BuilderMgr 构建类的管理类
type BuilderMgr struct {
    carBuilder   CarBuilder
    manorBuilder ManorBuilder
}

func (b BuilderMgr) buildCar(num int) []ToyInterface {
    var products []ToyInterface
    for i := 0; i < num; i++ {
        car := b.carBuilder.buildProduct()
        products = append(products, car)

        fmt.Printf("建造完成第%d辆%s", i+1, car.getName())
    }
    return products
}

func (b BuilderMgr) buildManor(num int) []ToyInterface {
    var products []ToyInterface
    for i := 0; i < num; i++ {
        manor := b.manorBuilder.buildProduct()
        products = append(products, manor)

        fmt.Printf("建造完成第%d辆%s\n", i+1, manor.getName())
    }
    return products
}

func main() {
    builderMgr := BuilderMgr{carBuilder: CarBuilder{ToyBuilder{}}}
    builderMgr.buildCar(4)
    fmt.Println()
    builderMgr.buildManor(2)
}

运行结果:

正在构建迷你小车......
迷你小车 增加了 4 个 轮子 
迷你小车 增加了 1 个 车身 
迷你小车 增加了 1 个 发动机 
迷你小车 增加了 1 个 方向盘 
建造完成第1辆迷你小车正在构建迷你小车......
迷你小车 增加了 4 个 轮子 
迷你小车 增加了 1 个 车身 
迷你小车 增加了 1 个 发动机 
迷你小车 增加了 1 个 方向盘 
建造完成第2辆迷你小车正在构建迷你小车......
迷你小车 增加了 4 个 轮子 
迷你小车 增加了 1 个 车身 
迷你小车 增加了 1 个 发动机 
迷你小车 增加了 1 个 方向盘 
建造完成第3辆迷你小车正在构建迷你小车......
迷你小车 增加了 4 个 轮子 
迷你小车 增加了 1 个 车身 
迷你小车 增加了 1 个 发动机 
迷你小车 增加了 1 个 方向盘 
建造完成第4辆迷你小车
正在构建淘淘小庄园......
淘淘小庄园 增加了 1 间 客厅 
淘淘小庄园 增加了 1 间 卧室 
淘淘小庄园 增加了 1 间 书房 
淘淘小庄园 增加了 1 间 厨房 
淘淘小庄园 增加了 1 个 花园 
淘淘小庄园 增加了 1 堵 围墙 
建造完成第1辆淘淘小庄园
正在构建淘淘小庄园......
淘淘小庄园 增加了 1 间 客厅 
淘淘小庄园 增加了 1 间 卧室 
淘淘小庄园 增加了 1 间 书房 
淘淘小庄园 增加了 1 间 厨房 
淘淘小庄园 增加了 1 个 花园 
淘淘小庄园 增加了 1 堵 围墙 
建造完成第2辆淘淘小庄园

4.1 模型说明

1.设计要点
构建模式(升级版)中主要有三个角色,在设计构建模式时要找到并区分这些角色。
(1)产品(Product):即你要构建的对象。
(2)构建者(Builder):构建模式的核心类,负责产品的构建过程。
(3)指挥者(BuilderManager):构建的管理类,负责管理每一种产品的创建数量和创建顺序。
2.构建模式的优缺点
优点:
(1)将产品(对象)的创建过程与产品(对象)本身分离开来,让使用方(调用者)可以用相同的创建过程创建不同的产品(对象)。
(2)将对象的创建过程单独分解出来,使得创建过程更加清晰,能够更加精确地控制复杂对象的创建过程。
(3)针对升级版的构建模式,每一个具体构建者都相对独立,而与其他的具体构建者无关,因此可以很方便地替换具体构建者或增加新的具体构建者。
缺点:
(1)增加了很多创建类,如果产品的类型和种类比较多,将会增加很多类,“使整个系统变得更加庞杂。
(2)产品之间的结构相差很大时,构建模式将很难适应。

五、应用场景

(1)产品(对象)的创建过程比较复杂,希望将产品的创建过程和它本身的功能分离开来。
(2)产品有很多种类,每个种类之间内部结构比较类似,但有很多差异;不同的创建顺序或不同的组合方式,将创建不同的产品。
资料:
人人都懂设计模式:从生活中领悟设计模式:Python实现

相关文章

  • 大话设计模式读书笔记-13建造者模式

    第13章 好菜没回味不同——建造者模式 定义 建造者模式将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同...

  • 07.构建者模式(创建型)

    创建型模式-构建者模式(生成器模式) 构建者模式为客户返回一个由多个部件组成的复杂产品。 一、构建者模式相关定义 ...

  • 第十二章:构建模式

    作为一个打工仔,在外面辛苦了一年,李力终于要回家过年了。李力给他的小侄子买了两套积木游戏玩具。小侄子玩的不亦乐乎,...

  • 安卓设计模式-构建者模式

    安卓设计模式-构建者模式 是什么 构建者模式又生builder模式,是将复杂的对象的构建与他的表示分离,使得同样的...

  • 建造者模式(Builder Pattern)

    Builder模式,建造者模式,构建器模式,生成器模式 意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过...

  • 构建者模式

    1.什么是构建者模式以及构建者模式的优点 构建者模式又称建造者模式,其主要功能是将一个复杂的对象的构建和表示进行分...

  • 2020-07-06

    《第三选择》樊登解读 + 个人总结 总结: 一、构建“第3选择”的思维模式 思维模式之一:我看到自己 永远拥有选择...

  • 构建者(Builder)模式

    不怕跌倒,所以飞翔 本文中知识点概述: 构建者模式的定义以及为什么要使用构建者模式; 构建者模式在Android中...

  • 设计模式-创建型-构建者模式

    基本概念: 构建者模式的定义将构建的过程和表示过程进行分离构建的过程:隐藏表示过程 : 开放 构建者模式的场景创建...

  • 设计模式[5]-构建者模式-Builder Pattern

    1. 构建者模式 构建者模式是创建型的设计模式,可以将复杂对象的创建过程和表示分离,使得同样的构建过程可以创建不同...

网友评论

      本文标题:第十二章:构建模式

      本文链接:https://www.haomeiwen.com/subject/lprkirtx.html