美文网首页
设计模式——builder

设计模式——builder

作者: 东方胖 | 来源:发表于2023-08-13 13:29 被阅读0次

对于创建型的问题,有一类问题不像工厂模式那样,面对一系列的产品,而是一个部分整体的关系。
比如造一个车,需要造发动机,轮胎,方向盘,车门,车窗,车灯,后备箱... 等等很多部分,电脑需要内存条件,芯片,键盘,鼠标,显示器,磁盘等等部件。

创建一个整体需要不同的部分。
但是每个部分是可以扩展,更换的,比如电脑的显示屏,不变的部分是,一台电脑总是基本上需要这些部件。

这种创建一个整体,但是部分的创建细节保留变化的问题,通常可以使用一种叫做 builder的设计模式来对付

Seperate the construction of a complex object from its represemtation so that the same construction process can create different representation.

将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示。
这句话一般不太容易读懂。有时候我甚至更愿意看代码。

构造,表示,分离... 很多大佬谈到设计模式的时候,常常有类似的词汇蹦出来。
我们要知道它是指代什么?
构造指的是一套逻辑动作,比如先做什么后做什么,表示,则是实现这些动作。
开头组装电脑,汽车的例子就是如此,我们知道一台电脑要若干个大件,先组装芯片 内存,显示器,是为构造,用什么牌子和规格的部件可以视为表示,当然实际问题中,所有的部件构造的细节都是“表示”需要关心的。

对于分离,耦合,通常没有编写过面向对象的程序员会不明所以。
分离是怎么样分离。

设计模式中所讲的分离,大概就是实现和接口可以独立变化,或者更具体一点,这里有虚函数,对于 java语言来说这里有 interface,可以 override的接口。
当你把一个动作声明为 虚函数接口,实际上,它就做到了所谓的分离了?

为什么会这样?

class A
{
public:
    virtual void move() = 0;
}
/*
client 代码,出现在某个上下文中
*/ 
A * p = new A();
p->move(); // p 到底是 A 的哪个派生类,在运行时决定

我们要改 move的动作,
派生 A,重新实现 move 的内部,这样client 的代码不会变化,说明接口和实现“分离”了,达到了各自变化扩展不影响的效果。

这种所谓的“分离”给代码维护带来很多可观的好处。

回到 builder 模式。
实现builder模式一般需要一个“导演”——把它当做是一个知道建造过程的角色,但是他不关心每个部分的构建细节。
代码代码概要

#include <list>
#include <iostream>


class Builder {
public:
    virtual void build() = 0;
};

class Computer;
class Director
{
public:

    void registerBuilder(Builder *builder) {
       m_builders.push_back(builder);
    }

    void construct() {
        for (Builder* builder: m_builders) {
            builder->build();
        }
        return ;
    }

private:
    std::list<Builder*> m_builders;
};


class MouseBuilder: public Builder
{
public:
    void build() {
        std::cout << "build mouse" << std::endl;
    }
};

class MonitorBuilder: public Builder
{
public:
    void build() {
        std::cout << "build monitor" << std::endl;
    }
};


int main(int argc, char *argv[])
{
    MonitorBuilder monitorBuilder;
    MouseBuilder mouseBuilder;
    Director d;
    d.registerBuilder(&monitorBuilder);
    d.registerBuilder(&mouseBuilder);
    d.construct();
    return 0;
}

导演类,视情况,可以做成一个单例。builder模式一般是对于步骤比较固定的创建型问题,比如固定的五个部分,所以上面的代码的持有 builder的方式可以不是用list,也可以用映射 map,或者直接持有每个builder的句柄。

这样的代码,扩展维护的时候,一般只是修改每个具体的builder的内部接口,对于Director及调用 Director的上下文,则不需要变更。
看起来很不错。

相关文章

网友评论

      本文标题:设计模式——builder

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