设计模式回顾——建造者模式(C++)

本文深入探讨了建造者模式,这是一种创建型设计模式,用于解耦复杂对象的构造与其表示。通过介绍建造者模式的组成、UML图、优缺点及应用场景,展示了如何在C++中实现建造者模式。此外,还对比了建造者模式与抽象工厂模式的区别。
摘要由CSDN通过智能技术生成


1 前言

  上一篇文章中对创建型设计模式之一的“工厂模式”进行概述与总结,分别描述了三种工厂模式(简单工厂、工厂方法、抽象工厂)的含义、特点、优缺点以及适用场景,并以C++语言实现具体例子。本文描述另一创建型设计模式——建造者模式。


2 什么是建造者模式

   建造者(Builder)模式,或者称为生成器模式,是创建型设计模式的一种。建造者模式是将一个复杂化对象的构造过程与其产品对象本身解耦,使得同样的构建过程可以创建不同的产品。利用构建模式,复杂化的对象被分解为多个简单的对象,然后每个分步构建每个简单对象;构建模式还将不变化部分抽象出来(如产品组成),变化部分可以灵活组合。


相关文章:

设计模式回顾——原型模式
设计模式回顾——观察者模式
设计模式回顾——模板模式
设计模式回顾——策略模式
设计模式回顾——适配器模式
设计模式回顾——建造者模式
设计模式回顾——工厂模式
设计模式回顾——单例模式
设计模式回顾——设计模式概念与基本原则


2.1 建造者模式组成

  建造者模式由产品(Product)、抽象建造者(Abstract Builder)、具体建造者(Concrete Builder)、指挥者(Director)、客户(Client)i五个要素组成。


  • 产品(Product), 由多个简单对象构成的复杂对象,各个简单对象由构建者建造

  • 抽象建造者(Abstract Builder), 声明产品各个子对象创建的抽象方法的接口,通常还提供一个返回复杂对象的方法GetProduct()

  • 具体建造者(Concrete Builder), 继承抽象建造者类,并实现抽象接口,即是实现产品各个子对象的具体创建方法

  • 指挥者(Director),调用建造者的各个子对象方法完成复杂对象的创建,指挥者不涉及具体产品信息

  • 客户(Client),客户和指挥者进行需求沟通,严格来说客户不属于建造者模式的一部分


2.2 建造者UML图

  根据建造者模式的组成要素,以及它们之间的关系,画出建造者模式的UML图如下。


在这里插入图片描述

建造者模式UML模型

3 建造者模式优缺点

优点:

  • 解耦

    将产品本身与产品创建过程进行解耦,客户不必关系创建细节,可以使用相同的创建过程来得到不同的产品;符合细节依赖抽象的“依赖倒转原则”

  • 精细地控制对象的创建过程
    将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程 。

  • 易于拓展
    增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。


不足:

  • 不适合产品之间差异很大的场景

    建造者模式一般用于创建具有较多的共同点的产品,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。

  • 不适合产品内部变化很复杂的场景

    如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。


4 什么地方使用建造者模式

   建造者模式的优点决定了其适用的场景,反过来其缺点即是其不适用的场景。建造者模式适用场景:

  • 组成相似、具有较多共同特点的复杂化产品对象,或者产品类因为调用顺序不同而产生不同作用
  • 分离复杂对象的创建和使用,期望相同创建过程可以创建不同的产品
  • 一个对象初始化时,需要较多的参数,或者参数具有默认值

  具体实例:

  • 汽车,由发动机、变速箱、车轮、方向盘、座椅等组成

  • 计算机,由主板、CPU、硬盘、内存、显卡、键盘、鼠标等组成


5 建造者模式实现

实例情况:

  • 目标是创建一个复杂化的产品(Product)
  • 这个产品由PartA、PartB、PartC三部分组成

实现过程:

  • 第一步,声明产品类
/* product.h */
#ifndef _PRODUCT_H_
#define _PRODUCT_H_

#include <string>
using namespace std;

class Product{
public:
	Product();
	~Product();

	void SetPartA(string part);
	void 
SetPartB(string part);
	void SetPartC(string part);
	void show();

private:
	string m_PartA;
	string m_PartB;
	string m_PartC;
};

#endif

  • 第二步,声明抽象建造者
/* abstract_builder.h */
#ifndef _ABSTRACT_BUILDER_H_
#define _ABSTRACT_BUILDER_H_

#include <string>
using namespace std;

class AbstractBuilder{
public:
	AbstractBuilder();
	virtual ~AbstractBuilder();

	virtual void CreateProduct() = 0;
	virtual void BuildPartA(string part) = 0;
	virtual void BuildPartB(string part) = 0;
	virtual void BuildPartC(string part) = 0;
	virtual Product* GetProduct() = 0;
};

#endif

  • 第三步,声明和构建具体建造者
/* builder.h */
#ifndef _BUILDER_H_
#define _BUILDER_H_

#include <string>
#include "product.h"
#include "abstract_builder.h"

using namespace std;

class Builder: public AbstractBuilder
{
public:
	Builder();
	~Builder();

	void CreateProduct();
	void BuildPartA(string part);
	void BuildPartB(string part);
	void BuildPartC(string part);

	Product* GetProduct();

private:
	Product* m_Product;
};

#endif


/* builder.cpp */
#include <iostream>
#include <stdio.h>
#include "builder.h"

Product::Product()
{
}
Product::~Product()
{
}

void Product::SetPartA(string param)
{
	m_PartA = param;
}

void Product::SetPartB(string param)
{
	m_PartB = param;
}

void Product::SetPartC(string param)
{
	m_PartC = param;
}

void Product::show()
{
	cout << "Output product,the component of product:" << m_PartA << " "
		<< m_PartB << " " << m_PartC << endl;
}

AbstractBuilder::AbstractBuilder()
{
}

AbstractBuilder::~AbstractBuilder()
{
}

Builder::Builder():m_Product(NULL)
{
}

Builder::~Builder()
{
}

void Builder::CreateProduct()
{
	cout << "Create a base product" << endl;
	m_Product = new Product();
}

void Builder::BuildPartA(string part)
{
	cout << "Building part A of the product" << endl;
	m_Product->SetPartA(part);
}

void Builder::BuildPartB(string part)
{
	cout << "Building part B of the product" << endl;
	m_Product->SetPartB(part);
}

void Builder::BuildPartC(string part)
{
	cout << "Building part C of the product" << endl;
	m_Product->SetPartC(part);
}

Product* Builder::GetProduct()
{
	return m_Product;
}

  • 第四步,声明和构建指挥者
/* directot.h */
#ifndef _DIRECTOR_H_
#define _DIRECTOR_H_

#include "builder.h"

class Director
{
public:
	Director(AbstractBuilder* builder);
	~Director();

	void Construct();

private:
	AbstractBuilder* m_Builder;
};
#endif

/* director.cpp */
#include <stdio.h>
#include "director.h"

Director::Director(AbstractBuilder* builder)
{
	m_Builder = builder;
}

Director::~Director()
{
}

void Director::Construct()
{
	if (NULL == m_Builder)
	{
		return;
	}
	m_Builder->CreateProduct();
	m_Builder->BuildPartA("PartA");
	m_Builder->BuildPartB("PartB");
	m_Builder->BuildPartC("PartC");
}

  • 第五步,用户调用指挥者创建产品对象
/* client.cpp */
#include "director.h"

int main(int argc, char **argv)
{
	AbstractBuilder *builder = new Builder();
	Director *director = new Director(builder);

	director->Construct();
	
	Product* product = builder->GetProduct();
	product->show();
	delete builder;
	delete director;
	return 0;
}

执行结果:

acuity@ubuntu:/mnt/hgfs/LSW/STHB/design-mode/builder$ g++ -o client client.cpp builder.cpp director.cpp
acuity@ubuntu:/mnt/hgfs/LSW/STHB/design-mode/builder$ ./client
Create a base product
Building part A of the product
Building part B of the product
Building part C of the product
Output product,the component of product:PartA PartB PartC

6 建造者模式与抽象工厂模式的比较

  创建者模式和抽象工厂模式都属于创建型设计模式,都是用于一个对象的“构建”,但两者又具有一定的不同点。

  • 产品复杂度不同

    建造者模式用于创建复杂化的产品对象;抽象工厂模式用于创建比较单一化的产品对象。如生产一台计算机和生产一个cpu的过程。

  • 产品“产出”形态不同

    建造者模式返回一个组装好的完整产品;抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族 。

  • 创建步骤和过程不同

    对于建造者模式,客户端不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,侧重于一步一步构造一个复杂对象,然后返回一个完整的对象 ;对于抽象工厂模式,客户端实例化工厂类,然后调用工厂方法获取所需产品对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Acuity.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值