[大话设计模式C++版] 第13章 好菜每回味不同 —— 建造者模式

源码可以在这里找到 大话设计模式C++版

建造小人一

实现画小人的程序

//Widget.cpp
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    createThin(painter);
    createFat(painter, 200);
}

void Widget::createThin(QPainter &painter, int x, int y)
{
    painter.drawEllipse(QRect(50+x, 20+y, 30, 30));
    painter.drawRect(60+x, 50+y, 10, 50);
    painter.drawLine(60+x, 50+y, 40+x, 100+y);
    painter.drawLine(70+x, 50+y, 90+x, 100+y);
    painter.drawLine(60+x, 100+y, 45+x, 150+y);
    painter.drawLine(70+x, 100+y, 85+x, 150+y);
}

void Widget::createFat(QPainter &painter, int x, int y)
{
    painter.drawEllipse(QRect(50+x, 20+y, 30, 30));
    painter.drawEllipse(QRect(45+x, 50+y, 40, 50));
    painter.drawLine(50+x, 50+y, 30+x, 100+y);
    painter.drawLine(80+x, 50+y, 100+x, 100+y);
    painter.drawLine(60+x, 100+y, 45+x, 150+y);
    painter.drawLine(70+x, 100+y, 85+x, 150+y);
}

建造小人二

创建两个类,不管谁都可以调用它们

#include <QPainter>

class PersonThinBuilder
{
public:
    PersonThinBuilder(QPainter* painter) {
        m_painter = painter;
    }
    void Build(int x=0, int y=0) {
        m_painter->drawEllipse(QRect(50+x, 20+y, 30, 30));
        m_painter->drawRect(60+x, 50+y, 10, 50);
        m_painter->drawLine(60+x, 50+y, 40+x, 100+y);
        m_painter->drawLine(70+x, 50+y, 90+x, 100+y);
        m_painter->drawLine(60+x, 100+y, 45+x, 150+y);
        m_painter->drawLine(70+x, 100+y, 85+x, 150+y);
    }

private:
    QPainter* m_painter;
};

胖小人类,类似受小人类。

//widget.cpp 客户端代码
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    PersonThinBuilder personThin(&painter);
    PersonFatBuilder personFat(&painter);
    personThin.Build();
    personFat.Build(150);
}

建造者模式

在这里插入图片描述

先抽象一个画小人的基类 PersonBuilder类

//PersonBuilder.h
class PersonBuilder
{
public:
    PersonBuilder(QPainter* painter, int x, int y) {
        m_painter = painter;
        m_x = x;
        m_y = y;
    }
    virtual void BuildHead() = 0;
    virtual void BuildBody() = 0;
    virtual void BuildArmLeft() = 0;
    virtual void BuildArmRight() = 0;
    virtual void BuildLegLeft() = 0;
    virtual void BuildLegRight() = 0;

protected:
    QPainter* m_painter;
    int m_x;
    int m_y;
};

具体小人类继承 PersonBuilder类

class PersonThinBuilder : public PersonBuilder
{
public:
    PersonThinBuilder(QPainter* painter, int x=0, int y=0) : PersonBuilder(painter, x, y) {}
    virtual void BuildHead() {
        m_painter->drawEllipse(QRect(50+m_x, 20+m_y, 30, 30));
    }
    virtual void BuildBody() {
        m_painter->drawRect(60+m_x, 50+m_y, 10, 50);
    }
    virtual void BuildArmLeft() {
        m_painter->drawLine(60+m_x, 50+m_y, 40+m_x, 100+m_y);
    }
    virtual void BuildArmRight() {
        m_painter->drawLine(70+m_x, 50+m_y, 90+m_x, 100+m_y);
    }
    virtual void BuildLegLeft() {
        m_painter->drawLine(60+m_x, 100+m_y, 45+m_x, 150+m_y);
    }
    virtual void BuildLegRight() {
        m_painter->drawLine(70+m_x, 100+m_y, 85+m_x, 150+m_y);
    }
};

还需要一个指挥画小人的类 PersonDirector类

//PersonDirector.h
class PersonDirector
{
private:
    std::shared_ptr<PersonBuilder> m_pb;
public:
    PersonDirector(std::shared_ptr<PersonBuilder> pb) : m_pb(pb) {}
    void CreatePerson() {
        m_pb->BuildHead();
        m_pb->BuildBody();
        m_pb->BuildArmLeft();
        m_pb->BuildArmRight();
        m_pb->BuildLegLeft();
        m_pb->BuildLegRight();
    }
};

客户端代码

//widget.cpp
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    auto ptb = std::shared_ptr<PersonThinBuilder>(new PersonThinBuilder(&painter));
    auto pdThin = std::shared_ptr<PersonDirector>(new PersonDirector(ptb));
    pdThin->CreatePerson();

    auto pfb = std::shared_ptr<PersonFatBuilder>(new PersonFatBuilder(&painter, 100));
    auto pdFat = std::shared_ptr<PersonDirector>(new PersonDirector(pfb));
    pdFat->CreatePerson();
}

Builder构建器模式 [李建忠C++笔记]

“对象创建”模式

  • 通过“对象创建”模式绕开new,来避免对像创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。
  • 典型模式
    • Factory Method
    • Abstract Factory
    • Prototype
    • Builder

动机(Motivation)

  • 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
  • 如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变。
class House {};

class HouseBuilder {
public:
    House* GetResult() {
        return pHouse;
    }
    virtual ~HouseBuilder() {}
public:
    House* pHouse;
    virtual void BuildPart1() = 0;
    virtual void BuildPart2() = 0;
    virtual bool BuildPart3() = 0;
    virtual void BuildPart4() = 0;
    virtual void BuildPart5() = 0;
};

class StoneHouse : public House {};

class StoneHouseBuilder : public HouseBuilder {
public:
    virtual void BuildPart1() {
        //pHouse->...
    }
    virtual void BuildPart2() {

    }
    virtual bool BuildPart3() {

    }
    virtual void BuildPart4() {
        
    }
    virtual void BuildPart5() {

    }
};

class HouseDirector {
public:
    HouseBuilder* pHouseBuilder;
    HouseDirector(HouseBuilder* pHouseBuilder) {
        this->pHouseBuilder = pHouseBuilder;
    }
    House* Construct() {
        pHouseBuilder->BuildPart1();

        for (int i = 0; i < 4; i++) {
            pHouseBuilder->BuildPart2();
        }

        bool flag = pHouseBuilder->BuildPart3();

        if (flag) {
            pHouseBuilder->BuildPart4();
        }

        pHouseBuilder->BuildPart5();

        return pHouseBuilder->GetResult();
    }
};

int main()
{
    StoneHouseBuilder* stoneHouseBuilder = new StoneHouseBuilder();
    HouseDirector* pHouseDirector = new HouseDirector(stoneHouseBuilder);
    pHouseDirector->Construct();
}

在这里插入图片描述

要点总结

  • Builder模式主要用于“分步骤构建一个复杂的对象”。在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。
  • 变化点在哪里,封装哪里——Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。
  • 在Builder模式中,要注意不同语言中构造器内调用虚函数的差别(C++ vs. C#)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值