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

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

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
适配器设计模式是一种结构型设计模式,它用于将一个类的接口转换为客户端所期望的另一个接口。在C语言中,可以通过以下步骤来实现适配器设计模式: 1. 首先,定义目标接口(Target Interface),这是客户端期望的接口。它可以是一个抽象基类或者一个纯虚函数。 ```c // 目标接口 typedef struct { void (*request)(void); } TargetInterface; ``` 2. 接下来,实现需要适配的类(Adaptee Class)。这个类拥有与目标接口不同的接口。 ```c // 需要适配的类 typedef struct { void (*specificRequest)(void); } AdapteeClass; void specificRequestImpl(void) { // 执行特定的操作 } ``` 3. 创建适配器类(Adapter Class),该类继承或包含目标接口,并将其方法委托给适配的类。 ```c // 适配器类 typedef struct { TargetInterface targetInterface; AdapteeClass* adaptee;} AdapterClass; void requestImpl(void) { AdapterClass* adapter = (AdapterClass*)this; adapter->adaptee->specificRequest(); } TargetInterface* createAdapter(AdapteeClass* adaptee) { AdapterClass* adapter = (AdapterClass*)malloc(sizeof(AdapterClass)); adapter->targetInterface.request = requestImpl; adapter->adaptee = adaptee; return &(adapter->targetInterface); } ``` 4. 最后,客户端可以通过目标接口来使用适配器。 ```c int main() { AdapteeClass adaptee; adaptee.specificRequest = specificRequestImpl; TargetInterface* adapter = createAdapter(&adaptee); adapter->request(); return 0; } ``` 上述代码演示了适配器设计模式的简单实现。通过适配器类的创建和使用,客户端可以通过目标接口调用适配的类的方法,实现了将两个不兼容接口之间的适配。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值