首页 > 编程语言 >C++实现设计模式——Builder模式

C++实现设计模式——Builder模式

时间:2024-08-19 10:40:29浏览次数:8  
标签:return Level int Builder C++ ID Player 设计模式 HP

C++实现设计模式——Builder模式

  • 建造者模式定义

建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

举例为什么用Builder模式

  • 举一个通俗的例子:

我们大家都玩游戏吧,每个角色会有很多属性,即构造参数,有一些是构造必需参数,如id,name,有一些是可以用默认的值,比如hp,level等等,游戏刚开始我们可以用默认值构造,但是当游戏过了一段时间这些属性都变得各不一样了,此时我们再次构造玩家角色的时候,只能是先构造一个初始化的,然后在后期修改赋值,如下:

Player *p1 = new Player ();
p1->setName("milo");
p1->setHp(1000);
p1->setleve(6);
```

  

但是这样有个不好的地方,那就是对象的构造过程是非连续的,也就是说对象可处于一个构造不完全的状态,我们很容易写出将对象传入各个方法,每个方法去赋值对象的某一部分这样的代码,这其实引入了一个状态空间,如果状态空间是强可控的,那还好(但依然提高了维护成本,你需要牢牢掌握住对象的构造过程,什么字段在何处被赋值);如果不可控,那么就很难保证这个对象是否被正确的构造,可能在某个方法中覆盖了某字段,也可能遗漏了某字段导致 错误。

那为了解决这个问题,建造者模式就出现了,就可以写成下面的这种方式

Player p1= PlayerBuilder.player()
                .name("milo")
                .hp(1000)
                .leve(6)
                .build();

  

需要构造什么参数,就加上哪个接口,其它的用默认值,这就可以绝对赋值哪个,这是第一个优点,还有一个优点,建造者模式可以随机组装构造参数的顺序,个数,这个在复杂构造的情况下很有用。

  • 结构图

 

  • 代码举例

 

#include <iostream>
#include <string>
using namespace std; 
 
class Player;
 
class playBuilder
{
    public:
        string Name;
        int ID;
        int HP;
        int Level;
    public:
        playBuilder() {    //参数默认值
            Name = "xiaoming";
            ID = 1001;
            HP = 100;
            Level = 1;
            cout<<"默认构造函数"<<endl;
        }
        playBuilder* SetName(string Name) {this->Name = Name;return this;}
        playBuilder* SetID(int ID) {this->ID = ID;return this;}
        playBuilder* SetHP(int HP) {this->HP = HP;return this;}
        playBuilder* SetLevel(int Level) {this->Level = Level;return this;}
        Player *build(); 
};
 
class Player {
    public:                 
        string Name;
        int ID;
        int HP;
        int Level;
    public:
        string GetName() {return Name;}
        int GetID() {return ID;}
        int GetHP() {return HP;}
        int GetLevel() {return Level;}
 
        Player() {cout<<"默认构造函数"<<endl;}
        Player (playBuilder const &temp) {
            this->Name = temp.Name;
            this->ID = temp.ID;
            this->HP = temp.HP;
            this->Level = temp.Level;
        }
        ~Player() {}
        void show() {
            cout<<Name<<"-"<<ID<<"-"<<HP<<"-"<<Level<<endl;
        }
};
 
Player *playBuilder::build(){
    return new Player(*this);
}
 
int main() {
    Player * p1 = playBuilder().SetID(90)->build();
    Player * p2 = playBuilder().SetID(91)->SetHP(200)->build();
    Player * p3 = playBuilder().SetName("zhangsan")->SetID(92)->build();
    p1->show();
    p2->show();
    p3->show();
    return 0;
}

 

上面这种情况就是我们要设置哪个参数就添加哪个方法set就行,对象是一个完整的创建过程,这也是我们很多地方比较常见的一种用法,它比正常的builder少了director角色,算是个简化版。

加入现在我们要求按照一定的规则进行构造,下面我们加上director,如果说builder是构造器,可以给我们随心构造的条件,那么director就好比一个指挥者,它规定着builder该怎么去创建一个目标对象。

#include <iostream>
#include <string>
using namespace std; 
 
class Player;
 
class playBuilder
{
    public:
        string Name;
        int ID;
        int HP;
        int Level;
    public:
        playBuilder() {    //参数默认值
            Name = "xiaoming";
            ID = 1001;
            HP = 100;
            Level = 1;
            cout<<"默认构造函数"<<endl;
        }
        playBuilder* SetName(string Name) {this->Name = Name;return this;}
        playBuilder* SetID(int ID) {this->ID = ID;return this;}
        playBuilder* SetHP(int HP) {this->HP = HP;return this;}
        playBuilder* SetLevel(int Level) {this->Level = Level;return this;}
        Player *build(); 
};
 
class Player {
    public:                 
        string Name;
        int ID;
        int HP;
        int Level;
    public:
        string GetName() {return Name;}
        int GetID() {return ID;}
        int GetHP() {return HP;}
        int GetLevel() {return Level;}
 
        Player() {cout<<"默认构造函数"<<endl;}
        Player (playBuilder const &temp) {
            this->Name = temp.Name;
            this->ID = temp.ID;
            this->HP = temp.HP;
            this->Level = temp.Level;
        }
        ~Player() {}
        void show() {
            cout<<Name<<"-"<<ID<<"-"<<HP<<"-"<<Level<<endl;
        }
};
 
Player *playBuilder::build(){
    return new Player(*this);
}
 
class Director {
    public:
        playBuilder *builder;
            Director() {
                builder = new playBuilder();
            }
            Player * construct(string Name,int ID,int HP,int Level) {   //构造规则
                builder = builder->SetName(Name);
                builder = builder->SetID(ID);
                builder = builder->SetHP(HP);
                builder = builder->SetLevel(Level);
                return builder->build();
            }
            ~ Director() {
                delete builder;
            }
};
 
int main() {
    Director d1;
    Player * p1 = d1.construct("xiaowang",999,9999,1);   //输入构建规则需要的参数
    Player * p2 = Director().construct("xiaosong",888,8888,8);
    Player * p3 = playBuilder().SetName("zhangsan")->SetID(92)->build();
    p1->show();
    p2->show();
    p3->show();
    return 0;
}

如图中所示,参数的构造顺序和需要构造哪些参数都在Director中决定了,如果需要多种规则方案,就往里面添加construct方法。

以上就是builder的设计方式相关了,只是简单的介绍了为什么要用,可以怎么用,具体的线程安全等等细节,在我们实际使用的时候还是要多考虑考虑的。

标签:return,Level,int,Builder,C++,ID,Player,设计模式,HP
From: https://www.cnblogs.com/jijm123/p/18366851

相关文章

  • Linux C++ 开发4 - 入门makefile一篇文章就够了
    1.make和Makefile1.1.什么是make?1.2.什么是Makefile?1.3.make与Makefile的关系2.Makefile的语法2.1.基本语法2.2.变量2.3.伪目标2.4.模式规则2.5.自动变量2.6.条件判断3.示例演示3.1.编译HelloWorld程序3.2.编译多文件项目3.2.1.项目......
  • C++-练习-21
     题目:编写一个程序,它要求用户输入其名,然后输入其姓。然后程序使用一个逗号和空格将姓和名组合起来,并存储和显示结果。请使用string对象和头文string中的函数。源代码:#define_CRT_SECURE_NO_WARNINGS //vs版本不加这个无法使用strcat等函数#include<iostream>#include......
  • C++-练习-22
    题目:结构CandyBar包含3个成员,第一个成员存储了糖块的品牌;第二个成员存储糖块的重量(可以有小数);第三个成员存储了糖块的卡路里含量(整数)。创建一个包含3个元素的CandyBar数组(使用new来动态分配数组),并将它们初始化为所选择的值,然后显示每个结构的内容源代码:#define_CRT_SECURE_......
  • C++ 各种初始化方法总结
    在各种编程语言中,初始化都是非常重要的步骤,用于确保对象在使用前具有确定的初始状态。C++提供了多种初始化方法,每种方法都有其特定的使用场景和注意事项。以下是一些主要的初始化方法及其注意事项:默认初始化(Default-initialization):形如Tobj、newT等方式的初始化,其中T为类......
  • 设计模式 单例模式
    单例模式的定义单例模式是指确保一个类在任何情况下都只有一个实例,并且提供一个访问该单例的全局访问点。如何创建一个单例模式构造函数需要是private访问权限的,这样才能避免外部通过new创建实例;考虑对象创建时的线程安全问题;考虑是否支持延迟加载;考虑getInstanc......
  • 设计模式 适配器模式
    适配器模式适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式的结构适配器模式通常涉及以下几个角色:目标(Target):定义客户端所期望的接口。适配者(Adaptee):定义一个已经存在......
  • 关于c++使用toml plusplus(俗称toml++)的使用(4)
    链接toml++-githubtoml++-帮助文档使用要求:c++17及以上版本toml语法-英文toml语法-中文toml读取参见官方给出的范例toml写入目标:表嵌套子表数组的写入比如:文件内容[NET_INTERFACE]bool=falsebool_arr=[false,false]complex_arr......
  • 关于c++使用toml plusplus(俗称toml++)的使用(3)
    链接toml++-githubtoml++-帮助文档使用要求:c++17及以上版本toml语法-英文toml语法-中文toml读取参见官方给出的范例toml写入目标:数组的写入文件内容[NET_INTERFACE]bool=falsebool_arr=[false,false]complex_arr=[false,'456'......
  • C++——new对象
    new对象与之前C的"类对象"方式有所不同,"类对象"方式并不会调用构造函数和析构函数,而new对象则会调用两个函数,释放该空间时用delete。数组申请int类型的数组#define_CRT_SECURE_NO_WARNINGS#include<iostream>usingnamespacestd;intmain(){ int*a=newint[10];......
  • C++中的多线程编程和锁机制
    二、多线程、锁2.1C语言线程库pthread(POSIXthreads)2.2.1线程创建pthread_create#include<pthread.h>pthread_tthread;ThreadDataargs={1,"Hellofromparameterizedthread"};intresult=pthread_create(&thread,attr,function,args); //线程创建即......