设计模式---建造者模式(Builder)

本文详细介绍了建造者模式,包括模式定义、结构、代码实现及优缺点。通过具体示例展示了如何在C++和Go中使用建造者模式构建产品对象,并通过指挥者类控制构建过程。此外,还分析了模式在肯德基点餐场景中的应用,揭示了建造者模式如何简化复杂对象的创建并提供灵活性。
摘要由CSDN通过智能技术生成

建造者模式—Builder

1.模式定义:

建造者模式(Builder ):将一个复杂对象的构建它的表示分离(解耦),使得同样的构建过程可以创建不同的表示(产品)。

2.模式结构

  • builder:抽象建造者
  • concretebuilderABC,concretebuilderAC :具体建造者
  • director:指挥者
  • product:产品角色
  • 在这里插入图片描述

3.代码分析

  • 3.1 main.cpp
#include<iostream>
#include"product.hpp"
#include"concretebuilder.hpp"
#include"director.hpp"

using namespace std;

int main() {
    cout << "==============concretebuilderABC=======================" << endl;
    product* pro_abc = new product();
    concretebuilderABC* builder_abc = new concretebuilderABC(pro_abc);
   
    director drc_abc;
    drc_abc.set_builder(builder_abc);
    pro_abc = drc_abc.construct();
    pro_abc->show();

    cout << "==============concretebuilderAC=======================" << endl;
    product* pro_ac = new product();
    concretebuilderAC* builder_ac = new concretebuilderAC(pro_ac);
    
    director drc_ac;
    drc_ac.set_builder(builder_ac);
    pro_ac = drc_ac.construct();
    pro_ac->show();

    return 0;
}
  • 3.2 抽象建造者: builder.hpp
#ifndef BUILDER_HPP
#define BUILDER_HPP

// 抽象建造接口
class builder
{
public:
    virtual ~builder(){};
    virtual void build_partA(){};
    virtual void build_partB(){};
    virtual void build_partC(){};
    
    virtual product* get_product(){ return nullptr; };
};
#endif // BUILDER_HPP
  • 3.3 具体建造者: concretebuilder.hpp
#ifndef CONCRETE_BUILDER_HPP
#define CONCRETE_BUILDER_HPP

#include<iostream>
#include"product.hpp"
#include"builder.hpp"
using namespace std;

// 具体建造类
class concretebuilderABC: public builder
{
private:
    product* m_product;
public:
    concretebuilderABC(product* pro): m_product(pro){};
    ~concretebuilderABC(){
        delete m_product;
    };

    void build_partA(){
        cout << "concretebuilderABC::build_partA" << endl;
        m_product->set_A();
    };

    void build_partB(){
        cout << "concretebuilderABC::build_partB" << endl;
        m_product->set_B();
    };

    void build_partC(){
        cout << "concretebuilderABC::build_partC" << endl;
        m_product->set_C();
    };

    product* get_product() {
        return m_product;
    };
};

// 具体建造类
class concretebuilderAC: public builder
{
private:
    product* m_product;
public:
    concretebuilderAC(product* pro): m_product(pro){};
    ~concretebuilderAC(){
        delete m_product;
    };

    void build_partA(){
        cout << "concretebuilderAC::build_partA" << endl;
        m_product->set_A();
    };

    void build_partB(){
       
    };

    void build_partC(){
        cout << "concretebuilderAC::build_partC" << endl;
        m_product->set_C();
    };

    product* get_product() {
        return m_product;
    };
};

#endif // CONCRETE_BUILDER_HPP

  • 3.4 指挥者: director.hpp
#ifndef DIRECTOR_HPP
#define DIRECTOR_HPP

#include"product.hpp"
#include"builder.hpp"

// 指挥者
class director
{
private:
    builder* m_builder;
public:
    director(){};
    ~director(){
        delete m_builder;
    };

    void init_builder(builder* bld){
        if (!bld) {
            return;
        }

        m_builder = bld;
    };

    void set_builder(builder* bld){
        init_builder(bld);
    };

    product* construct() {
        if (!m_builder) {
            return nullptr;
        }

        m_builder->build_partA();
        m_builder->build_partB();
        m_builder->build_partC();
        
        return m_builder->get_product();
    };
};

#endif // DIRECTOR_HPP
  • 3.5 产品: product.hpp
#ifndef PRODUCT_HPP
#define PRODUCT_HPP

#include<iostream>
using namespace std;

// 产品
class product{
public:
    product(){};
    ~product(){};

    void set_A() {
        cout << "product::set_A" << endl;
    };

    void set_B() {
        cout << "product::set_B" << endl;
    };

    void set_C() {
        cout << "product::set_C" << endl;
    };

    void show(){
        cout << "product::show" << endl;
    };
};

#endif // PRODUCT_HPP
  • 3.6 实验结果:
==============concretebuilderABC=======================
concretebuilderABC::build_partA
product::set_A
concretebuilderABC::build_partB
product::set_B
concretebuilderABC::build_partC
product::set_C
product::show
==============concretebuilderAC======================= 
concretebuilderAC::build_partA
product::set_A
concretebuilderAC::build_partC
product::set_C
product::show

4.优缺点

  • 4.1 优点

    • 4.1.1 在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
    • 4.1.2 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
    • 4.1.3 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
    • 4.1.4 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
  • 4.2 缺点

    • 4.2.1 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
    • 4.2.2 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

5.模式分析

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

  • 5.2 建造者模式的结构中还引入了一个指挥者类Director,该类的作用主要有两个:一方面它隔离了客户与生产过程;另一方面它负责控制产品的生成过程。指挥者针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象;

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

6.实例:肯德基点餐(go代码实现)

  • 6.0: main.go
package main

import (
	"fmt"
	"./builder"
)


func test_builder() {
	cbld := builder.NewConcreteBuilder()
	
	fmt.Println("before builder meal:")
	cbld.GetMeal().Show()
	drc := builder.NewDirector(cbld)
	drc.Construct("keli", "zhaji")
	fmt.Println("afore builder meal:")
	cbld.GetMeal().Show()
}

func main() {
	test_builder()
}
  • 6.1:套餐:meal.go
package builder

import "fmt"

// 套餐
type Meal struct {
	food  string
	drink string
}

func NewMeal(food, drink string) *Meal {
	return &Meal{
		food:  food,
		drink: drink,
	}
}

func (m *Meal) set_food(food string) {
	m.food = food
}

func (m *Meal) set_drink(drink string) {
	m.drink = drink
}

func (m *Meal) Show() {
	fmt.Println("food:", m.food)
	fmt.Println("drink:", m.drink)
}

  • 6.2: 创建类:builder.go
package builder

// 创建接口
type IBuilder interface {
	BuildDrink(string)
	BuildFood(string)
}

// =====================================================

// 具体创建
type ConcreteBuilder struct {
	meal *Meal
}

func NewConcreteBuilder() *ConcreteBuilder {
	return &ConcreteBuilder{
		meal: NewMeal("", ""),
	}
}

func (cbld *ConcreteBuilder) BuildDrink(drink string) {
	cbld.meal.set_drink(drink)
}

func (cbld *ConcreteBuilder) BuildFood(food string) {
	cbld.meal.set_food(food)
}

func (cbld ConcreteBuilder) GetMeal() *Meal {
	return cbld.meal
}
  • 6.3: 指挥者:director.go
package builder

// 指挥者
type Director struct {
	Builder 	IBuilder
}

func NewDirector(builder IBuilder) *Director {
	return &Director{
		Builder: builder,
	}
}
// 构造具体的套餐
func (drc *Director) Construct(drink, food string) {
	drc.Builder.BuildDrink(drink)
	drc.Builder.BuildFood(food)
}

func (drc *Director) SetMealBuilder(builer IBuilder) {
	drc.Builder = builer
}
  • 6.4 执行结果:
before builder meal:
food: 
drink:
afore builder meal:
food: zhaji
drink: keli
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值