前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式:建造者模式

设计模式:建造者模式

作者头像
王强
发布2018-08-09 17:27:38
2750
发布2018-08-09 17:27:38
举报
文章被收录于专栏:Python爬虫实战

1 概述

在生活中存在很多复杂的对象,就拿我们每天都见到的汽车举例,它由轮胎、方向盘、发动机、外壳等各种部件组成的,可谓是相当复杂。

汽车组装过程

作为一个普通消费者,我们并不关心各部件送入工厂和工厂组装的过程和细节,我们关心的只是这辆完整的汽车。用创建者模式对其进行描述:各部件和组装过程分开,一步步创建一个复杂的对象,用户只需要指定复杂对象的类型就可以得到该对象,而无需知道内部具体构造细节。

建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以 创建不同的表示。根据中文翻译的不同,也可以成为生成器模式

2 图解

抽象建造者类中定义了产品的创建方法和返回方法。

建造者模式的结构中还引入了一个指挥者类Director,该类的作用主要有两个:

  • 隔离 了客户与生产过程;
  • 负责控制产品的生成过程。

指挥者针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整 的产品对象。

在客户端代码中,无须关心产品对象的具体组装过程,只需确定具体建造者的类型即可,建造者模式将复杂对象的构建与对象的表现分离开来,这样使得同样的构建过程可以创建出不同的表现。

Builder图解

创建者模式包含如下角色:

  • Builder:抽象建造者
  • ConcreteBuilder:具体建造者
  • Director:指挥者
  • Product:产品角色

3 优缺点

优点:

  • 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建者过程可以创建不同的产品对象。
  • 每一个具体建造者相对独立,因此可以很方便替换具体建造者或增加新的具体建造者。
  • 可以更加精细地控制产品的创建过程。
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统拓展方便,符合“开闭原则”。

缺点:

  • 该模式所创建的产品一般具有较多的共同点,如果产品之间差异很大,此模式不适合。
  • 如果产品内部变化复杂,可能导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

4 应用场景

在以下情况下可以使用建造者模式:

  • 需要生成的产品对象有复杂的内部结构,这些产品对象包含多个成员属性。
  • 需要生成的产品对象的属性相互依赖,需要制定其生成顺序。
  • 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不再建造者类中。
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

5 实例

Builder_Uml

5.1 Python代码

代码语言:javascript
复制
#-*- coding: utf-8 -*-

'''
  建造者模式
'''

class Product(object):
    """产品类"""
    def __init__(self):
        super(Product, self).__init__()
        self.__description = ''

    def step(self, strstep):
        self.__description += "-->" + strstep

    def show_description(self):
        print(self.__description)

class Builder(object):
    """建造者类"""
    def build_partA(self):
        pass

    def build_partB(self):
        pass

    def build_partC(self):
        pass

    def get_result(self):
        return 0


class ConcreteBuilder1(Builder):
    """第一种建造方式"""
    def __init__(self):
        super(ConcreteBuilder1, self).__init__()
        self.__product = Product()

    def build_partA(self):
        self.__product.step('first')

    def build_partB(self):
        self.__product.step('second')

    def build_partC(self):
        self.__product.step('third')

    def get_result(self):
        return self.__product


class ConcreteBuilder2(Builder):
    """第二种建造方式"""
    def __init__(self):
        super(ConcreteBuilder2, self).__init__()
        self.__product = Product()

    def build_partA(self):
        self.__product.step('A')

    def build_partB(self):
        self.__product.step('B')

    def build_partC(self):
        self.__product.step('C')

    def get_result(self):
        return self.__product    

class Direcotr(object):
    """指挥者类"""
    def construct(self):
        self.__builder.build_partA()
        self.__builder.build_partB()
        self.__builder.build_partC()

    def set_builder(self, builder):
        self.__builder = builder


if __name__ == '__main__':
    director = Direcotr()
    builder1 = ConcreteBuilder1()
    builder2 = ConcreteBuilder2()

    # 调用第一种建造方式
    print('===== First way =====')
    director.set_builder(builder1)
    director.construct()
    product1 = builder1.get_result()
    product1.show_description()

    # 调用第二种建造方式
    print('===== Second way =====')
    director.set_builder(builder2)
    director.construct()
    product1 = builder2.get_result()
    product1.show_description()

运行结果:

代码语言:javascript
复制
===== First way =====
-->first-->second-->third
===== Second way =====
-->A-->B-->C

5.2 C++实现

  • product.h
代码语言:javascript
复制
#ifndef PRODUCT_H
#define PRODUCT_H

#include <iostream>
#include <string>

using namespace std;

// 产品类
class Product
{
public:
    Product() {
        m_description = "";
    }

    void step(string strstep)
    {
        m_description += "-->" + strstep;
    }

    void showDescription()
    {
        cout << m_description << endl;
    }

private:
    string m_description;
};
#endif // PRODUCT_H
  • builder.h
代码语言:javascript
复制
#ifndef BUILDER_H
#define BUILDER_H

#include "product.h"

// 建造者类
class Builder
{
public:
    Builder() {}
    virtual ~Builder() {}

    virtual void buildPartA() {}
    virtual void buildPartB() {}
    virtual void buildPartC() {}
    virtual Product* getResult()=0;
};

// 第一种建造方式
class ConcreteBuilder1: public Builder
{
private:
    Product* m_product;

public:
    ConcreteBuilder1()
    {
        m_product = new Product();
    }
    virtual ~ConcreteBuilder1(){}

    virtual void buildPartA()
    {
        m_product->step("first");
    }

    virtual void buildPartB()
    {
        m_product->step("second");
    }

    virtual void buildPartC()
    {
        m_product->step("third");
    }

    virtual Product* getResult()
    {
        return m_product;
    }
};

// 第二种建造方式
class ConcreteBuilder2: public Builder
{
private:
    Product* m_product;

public:
    ConcreteBuilder2()
    {
        m_product = new Product();
    }

    virtual ~ConcreteBuilder2() {}

    virtual void buildPartA()
    {
        m_product->step("A");
    }

    virtual void buildPartB()
    {
        m_product->step("B");
    }

    virtual void buildPartC()
    {
        m_product->step("C");
    }

    virtual Product* getResult()
    {
        return m_product;
    }
};

#endif // BUILDER_H
  • director.cpp
代码语言:javascript
复制
#ifndef DIRECTOR_H
#define DIRECTOR_H

#include "builder.h"

// 指挥者类
class Director
{
public:
    Director() {}

    void construct()
    {
        m_builder->buildPartA();
        m_builder->buildPartB();
        m_builder->buildPartC();
    }

    void setBuilder(Builder* builder)
    {
        m_builder = builder;
    }
private:
    Builder* m_builder;
};

#endif // DIRECTOR_H
  • main.cpp
代码语言:javascript
复制
#include <iostream>
#include "director.h"

using namespace std;

int main()
{
    Director *pDirector = new Director();
    Builder *pBuilder1 = new ConcreteBuilder1();
    Builder *pBuilder2 = new ConcreteBuilder2();

    // 调用第一种建造方式
    cout << "===== First way =====" << endl;
    pDirector->setBuilder(pBuilder1);
    pDirector->construct();
    Product *pProduct1 = pBuilder1->getResult();
    pProduct1->showDescription();

    cout << "===== Second way =====" << endl;
    pDirector->setBuilder((pBuilder2));
    pDirector->construct();
    Product *pProduct2 = pBuilder2->getResult();
    pProduct2->showDescription();

    return 0;
}

运行结果:

代码语言:javascript
复制
===== First way =====
-->first-->second-->third
===== Second way =====
-->A-->B-->C
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 C与Python实战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 概述
  • 2 图解
  • 3 优缺点
  • 4 应用场景
  • 5 实例
    • 5.1 Python代码
      • 5.2 C++实现
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档