C++ 设计模式——建造者模式

建造者模式

    • 建造者模式
      • 组成部分
      • 建造者模式使用步骤
        • 1. 定义产品类
        • 2. 创建具体产品类
        • 3. 创建建造者接口
        • 4. 实现具体建造者
        • 5. 创建指挥者类
        • 6. 客户端代码
      • 建造者模式 UML 图
      • 建造者模式 UML 图解析
      • 建造者模式的优缺点
      • 建造者模式的适用场景
      • 完整代码

建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,它允许使用多个简单的对象一步步构建一个复杂的对象。建造者模式通过将对象的构建过程与表示分离,使得同样的构建过程可以创建不同的表示。

引入“建造者”模式的定义:将一个复杂的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

组成部分

  • 产品(Product):代表最终构建的复杂对象,包含多个部件和属性。产品类定义了对象的结构和行为,通常包括多个属性和方法。
  • 建造者(Builder):定义创建产品的各个部件的抽象接口。建造者接口提供了构建不同部分的方法,允许灵活地创建不同类型的产品。
  • 具体建造者(ConcreteBuilder):实现建造者接口,具体构建和装配产品的各个部件。每个具体建造者负责创建特定类型的产品,同时维护构建过程的状态。
  • 指挥者(Director):负责管理建造过程,调用建造者的方法以生成产品。指挥者定义构建的顺序,确保产品的构建过程符合预期。

建造者模式使用步骤

1. 定义产品类

首先定义一个复杂对象的类 Monster,它是所有怪物的基类。

//怪物父类
class Monster
{
public:virtual ~Monster() {} //做父类时析构函数应该为虚函数// 其他方法可以在这里定义
};
2. 创建具体产品类

创建多个具体的怪物类,继承自 Monster 类。

//亡灵类怪物
class M_Undead :public Monster{};//元素类怪物
class M_Element :public Monster{};//机械类怪物
class M_Mechanic :public Monster{};
3. 创建建造者接口

定义一个抽象建造者类 MonsterBuilder,声明构建产品各个部分的方法。

//怪物构建器父类
class MonsterBuilder
{
public:virtual ~MonsterBuilder() {} //做父类时析构函数应该为虚函数//返回指向Monster类的成员变量指针m_pMonster,当一个复杂的对象构建完成后,可以通过该成员函数把对象返回Monster* GetResult(){return m_pMonster;}virtual void LoadTrunkModel(string strno) = 0;//这里也可以写为空函数体,子类决定是否重新实现virtual void LoadHeadModel(string strno) = 0;virtual void LoadLimbsModel(string strno) = 0;protected:Monster* m_pMonster;  //指向Monster类的成员变量指针
};
4. 实现具体建造者

创建多个具体建造者类,负责构建不同类型的怪物。

//亡灵类怪物构建器类
class M_UndeadBuilder :public MonsterBuilder
{
public:M_UndeadBuilder() //构造函数{m_pMonster = new M_Undead();}virtual void LoadTrunkModel(string strno){cout << "载入亡灵类怪物的躯干部位模型,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//具体要做的事情其实是委托给怪物子类来完成,委托指把本该自己实现的功能转给其他类实现//m_pMonster->......略}virtual void LoadHeadModel(string strno){cout << "载入亡灵类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}virtual void LoadLimbsModel(string strno){cout << "载入亡灵类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}
};//元素类怪物构建器类
class M_ElementBuilder :public MonsterBuilder
{
public:M_ElementBuilder() //构造函数{m_pMonster = new M_Element();}virtual void LoadTrunkModel(string strno){cout << "载入元素类怪物的躯干部位模型,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略			}virtual void LoadHeadModel(string strno){cout << "载入元素类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}virtual void LoadLimbsModel(string strno){cout << "载入元素类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}
};
//机械类怪物构建器类
class M_MechanicBuilder :public MonsterBuilder
{
public:M_MechanicBuilder() //构造函数{m_pMonster = new M_Mechanic();}virtual void LoadTrunkModel(string strno){cout << "载入机械类怪物的躯干部位模型,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}virtual void LoadHeadModel(string strno){cout << "载入机械类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}virtual void LoadLimbsModel(string strno){cout << "载入机械类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}
};
5. 创建指挥者类

定义一个指挥者类 MonsterDirector,负责管理建造过程。

//指挥者类
class MonsterDirector
{
public:MonsterDirector(MonsterBuilder* ptmpBuilder) //构造函数{m_pMonsterBuilder = ptmpBuilder;}//指定新的构建器void SetBuilder(MonsterBuilder* ptmpBuilder){m_pMonsterBuilder = ptmpBuilder;}//原MonsterBuilder类中的Assemble成员函数Monster* Construct(string strmodelno) //参数:模型编号,形如“1253679201245”等,每些位的组合都有一些特别的含义,这里无需深究{m_pMonsterBuilder->LoadTrunkModel(strmodelno.substr(4, 3));  //载入躯干模型,截取某部分字符串以表示躯干模型的编号m_pMonsterBuilder->LoadHeadModel(strmodelno.substr(7, 3));   //载入头部模型并挂接到躯干模型上m_pMonsterBuilder->LoadLimbsModel(strmodelno.substr(10, 3)); //载入四肢模型并挂接到躯干模型上return m_pMonsterBuilder->GetResult();  //返回构建后的对象}
private:MonsterBuilder* m_pMonsterBuilder; //指向所有构建器类的父类
};
6. 客户端代码

在客户端中,创建具体建造者和指挥者的实例,使用指挥者构建产品。

int main() 
{// 创建亡灵类怪物建造者M_UndeadBuilder* undeadBuilder = new M_UndeadBuilder();MonsterDirector undeadDirector(undeadBuilder); // 创建亡灵类怪物的指挥者// 构建亡灵类怪物Monster* undeadMonster = undeadDirector.Construct("1253679201245");// 使用构建的亡灵类怪物对象// ...// 创建元素类怪物的建造者M_ElementBuilder* elementBuilder = new M_ElementBuilder();MonsterDirector elementDirector(elementBuilder); // 创建元素类怪物的指挥者// 构建元素类怪物Monster* elementMonster = elementDirector.Construct("1253679201245");// 使用构建的元素类怪物对象// ...// 创建机械类怪物的建造者M_MechanicBuilder* mechanicBuilder = new M_MechanicBuilder();MonsterDirector mechanicDirector(mechanicBuilder); // 创建机械类怪物的指挥者// 构建机械类怪物Monster* mechanicMonster = mechanicDirector.Construct("1253679201245");// 使用构建的机械类怪物对象// ...// 清理资源delete undeadMonster; // 释放亡灵类怪物对象delete elementMonster; // 释放元素类怪物对象delete mechanicMonster; // 释放机械类怪物对象delete undeadBuilder; // 释放亡灵类建造者对象delete elementBuilder; // 释放元素类建造者对象delete mechanicBuilder; // 释放机械类建造者对象return 0;
}

建造者模式 UML 图

建造者模式 UML 图

建造者模式 UML 图解析

  • Builder (抽象构建器)
    • MonsterBuilder 类定义了创建产品对象的各个部件的抽象接口,包括方法如 LoadTrunkModelLoadHeadModelLoadLimbsModel。同时,它还定义了 GetResult 接口,用于返回所创建的复杂对象。
  • ConcreteBuilder (具体构建器)
    • 具体构建器类(如 M_UndeadBuilderM_ElementBuilderM_MechanicBuilder)实现了 MonsterBuilder 接口,负责具体的构造和装配过程。每个具体构建器定义了其所创建的复杂对象(如 M_UndeadM_ElementM_Mechanic),并可能提供方法返回创建好的复杂对象。
  • Product (产品)
    • 产品类指被构建的复杂对象,包含多个部件。具体构建器负责创建该产品的内部表示并定义它的装配过程。例如,M_UndeadM_ElementM_Mechanic 类分别表示不同类型的怪物。
  • Director (指挥者)
    • MonsterDirector 类是指挥者,持有一个指向抽象构建器的引用(如 m_pMonsterBuilder)。它利用该引用在 Construct 成员函数中调用构建器对象的方法,完成复杂对象的构建。指挥者控制构建过程的顺序,确保各个部件按正确的顺序装配。例如,Construct 函数中会依次调用 LoadTrunkModelLoadHeadModelLoadLimbsModel
  • 客户端
    • 在客户端(如 main 函数)中,用户只需生成一个具体的构建器对象,并利用该构建器对象创建指挥者对象,调用指挥者的 Construct 方法,就可以构建出所需的复杂对象。这种设计使得客户端与具体实现解耦,提高了灵活性和可维护性。

建造者模式的优缺点

优点

  • 解耦:建造者模式将复杂对象的构建与表示分离,使得构建过程与产品的表示相互独立,降低了模块间的耦合度。
  • 灵活性:可以通过更换具体建造者来灵活地构建不同类型的产品,而无需修改指挥者或客户端代码。
  • 可读性和可维护性:通过清晰的接口和结构,增加了代码的可读性,便于后续的维护和扩展。
  • 支持复杂对象的构建:适合构建复杂对象,特别是那些具有多个部件和装配顺序要求的对象。
  • 步骤控制:指挥者可以控制构建的步骤和顺序,确保复杂对象按照预期的方式构建。

缺点

  • 复杂性:对于简单对象的构建,使用建造者模式可能显得过于复杂,增加了不必要的代码和结构。
  • 类的数量增加:需要创建多个具体建造者类和产品类,可能导致类的数量增加,增加了系统的复杂性。
  • 构建过程固定:一旦定义了指挥者的构建过程,可能不够灵活,难以适应一些动态变化的需求。

建造者模式的适用场景

  • 构建复杂对象:当对象由多个部件组成,且构建和组合过程复杂时,例如游戏中的角色(如怪物、NPC)。
  • 产品变体多样化:当需要创建多种不同类型的产品,但构建过程相似时,例如不同类型的车辆(轿车、卡车、摩托车)。
  • 构建过程需要控制:当构建过程需要明确的步骤和顺序时,例如根据不同条件动态调整构建顺序。
  • 对象的构建与表示分离:当产品的构建与表示需要解耦,以便于后续维护和扩展,例如构建复杂文档时。
  • 逐步构建对象:当对象的构建过程需要分步进行,或在构建过程中进行条件判断时,例如配置复杂系统。
  • 需要灵活的对象创建:当需要在运行时决定构建哪种类型的对象时,例如根据用户输入或配置文件动态选择不同的构建器。

完整代码

#include <iostream>
#include <string>using namespace std;//怪物父类
class Monster
{
public:virtual ~Monster() {} //做父类时析构函数应该为虚函数//void Assemble(string strmodelno) //参数:模型编号,形如“1253679201245”等,每些位的组合都有一些特别的含义,这里无需深究//{//	LoadTrunkModel(strmodelno.substr(4, 3));  //载入躯干模型,截取某部分字符串以表示躯干模型的编号//	LoadHeadModel(strmodelno.substr(7, 3));   //载入头部模型并挂接到躯干模型上//	LoadLimbsModel(strmodelno.substr(10, 3)); //载入四肢模型并挂接到躯干模型上//}//virtual void LoadTrunkModel(string strno) = 0; //这里也可以写为空函数体,子类决定是否重新实现//virtual void LoadHeadModel(string strno) = 0;//virtual void LoadLimbsModel(string strno) = 0;
};//亡灵类怪物
class M_Undead :public Monster
{/*public:virtual void LoadTrunkModel(string strno){cout << "载入亡灵类怪物的躯干部位模型,需要调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}virtual void LoadHeadModel(string strno){cout << "载入亡灵类怪物的头部模型并挂接到躯干部位,需要调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}virtual void LoadLimbsModel(string strno){cout << "载入亡灵类怪物的四肢模型并挂接到躯干部位,需要调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}*/
};//元素类怪物
class M_Element :public Monster
{/*public:virtual void LoadTrunkModel(string strno){cout << "载入元素类怪物的躯干部位模型,需要调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}virtual void LoadHeadModel(string strno){cout << "载入元素类怪物的头部模型并挂接到躯干部位,需要调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}virtual void LoadLimbsModel(string strno){cout << "载入元素类怪物的四肢模型并挂接到躯干部位,需要调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}*/
};//机械类怪物
class M_Mechanic :public Monster
{/*public:virtual void LoadTrunkModel(string strno){cout << "载入机械类怪物的躯干部位模型,需要调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}virtual void LoadHeadModel(string strno){cout << "载入机械类怪物的头部模型并挂接到躯干部位,需要调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}virtual void LoadLimbsModel(string strno){cout << "载入机械类怪物的四肢模型并挂接到躯干部位,需要调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;}*/
};//-----------------
//怪物构建器父类
class MonsterBuilder
{
public:virtual ~MonsterBuilder() {} //做父类时析构函数应该为虚函数//void Assemble(string strmodelno) //参数:模型编号,形如“1253679201245”等,每些位的组合都有一些特别的含义,这里无需深究//{//	LoadTrunkModel(strmodelno.substr(4, 3));  //载入躯干模型,截取某部分字符串以表示躯干模型的编号//	LoadHeadModel(strmodelno.substr(7, 3));   //载入头部模型并挂接到躯干模型上//	LoadLimbsModel(strmodelno.substr(10, 3)); //载入四肢模型并挂接到躯干模型上//}//返回指向Monster类的成员变量指针m_pMonster,当一个复杂的对象构建完成后,可以通过该成员函数把对象返回Monster* GetResult(){return m_pMonster;}virtual void LoadTrunkModel(string strno) = 0;//这里也可以写为空函数体,子类决定是否重新实现virtual void LoadHeadModel(string strno) = 0;virtual void LoadLimbsModel(string strno) = 0;protected:Monster* m_pMonster;  //指向Monster类的成员变量指针
};//---------------
//亡灵类怪物构建器类
class M_UndeadBuilder :public MonsterBuilder
{
public:M_UndeadBuilder() //构造函数{m_pMonster = new M_Undead();}virtual void LoadTrunkModel(string strno){cout << "载入亡灵类怪物的躯干部位模型,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//具体要做的事情其实是委托给怪物子类来完成,委托指把本该自己实现的功能转给其他类实现//m_pMonster->......略}virtual void LoadHeadModel(string strno){cout << "载入亡灵类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}virtual void LoadLimbsModel(string strno){cout << "载入亡灵类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}
};//元素类怪物构建器类
class M_ElementBuilder :public MonsterBuilder
{
public:M_ElementBuilder() //构造函数{m_pMonster = new M_Element();}virtual void LoadTrunkModel(string strno){cout << "载入元素类怪物的躯干部位模型,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略			}virtual void LoadHeadModel(string strno){cout << "载入元素类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}virtual void LoadLimbsModel(string strno){cout << "载入元素类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}
};
//机械类怪物构建器类
class M_MechanicBuilder :public MonsterBuilder
{
public:M_MechanicBuilder() //构造函数{m_pMonster = new M_Mechanic();}virtual void LoadTrunkModel(string strno){cout << "载入机械类怪物的躯干部位模型,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}virtual void LoadHeadModel(string strno){cout << "载入机械类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}virtual void LoadLimbsModel(string strno){cout << "载入机械类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;//m_pMonster->......略}
};//指挥者类
class MonsterDirector
{
public:MonsterDirector(MonsterBuilder* ptmpBuilder) //构造函数{m_pMonsterBuilder = ptmpBuilder;}//指定新的构建器void SetBuilder(MonsterBuilder* ptmpBuilder){m_pMonsterBuilder = ptmpBuilder;}//原MonsterBuilder类中的Assemble成员函数Monster* Construct(string strmodelno) //参数:模型编号,形如“1253679201245”等,每些位的组合都有一些特别的含义,这里无需深究{m_pMonsterBuilder->LoadTrunkModel(strmodelno.substr(4, 3));  //载入躯干模型,截取某部分字符串以表示躯干模型的编号m_pMonsterBuilder->LoadHeadModel(strmodelno.substr(7, 3));   //载入头部模型并挂接到躯干模型上m_pMonsterBuilder->LoadLimbsModel(strmodelno.substr(10, 3)); //载入四肢模型并挂接到躯干模型上return m_pMonsterBuilder->GetResult();  //返回构建后的对象}
private:MonsterBuilder* m_pMonsterBuilder; //指向所有构建器类的父类
};int main()
{// 创建具体建造者M_UndeadBuilder* undeadBuilder = new M_UndeadBuilder();MonsterDirector undeadDirector(undeadBuilder); // 创建亡灵类怪物的指挥者// 构建亡灵类怪物Monster* undeadMonster = undeadDirector.Construct("1253679201245");// 使用构建的亡灵类怪物对象// ...// 创建元素类怪物的建造者M_ElementBuilder* elementBuilder = new M_ElementBuilder();MonsterDirector elementDirector(elementBuilder); // 创建元素类怪物的指挥者// 构建元素类怪物Monster* elementMonster = elementDirector.Construct("1253679201245");// 使用构建的元素类怪物对象// ...// 创建机械类怪物的建造者M_MechanicBuilder* mechanicBuilder = new M_MechanicBuilder();MonsterDirector mechanicDirector(mechanicBuilder); // 创建机械类怪物的指挥者// 构建机械类怪物Monster* mechanicMonster = mechanicDirector.Construct("1253679201245");// 使用构建的机械类怪物对象// ...// 清理资源delete undeadMonster; // 释放亡灵类怪物对象delete elementMonster; // 释放元素类怪物对象delete mechanicMonster; // 释放机械类怪物对象delete undeadBuilder; // 释放亡灵类建造者对象delete elementBuilder; // 释放元素类建造者对象delete mechanicBuilder; // 释放机械类建造者对象return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/403909.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言—指针(1)

目录 一、内存和地址 &#xff08;1.1&#xff09;内存 &#xff08;1.2&#xff09;编址的理解 二、指针变量和地址 &#xff08;2.1&#xff09;取地址操作符&#xff08;&&#xff09; &#xff08;2.2&#xff09;指针变量和解引用操作符 &#xff08;2.2.1&…

XSS复现

目录 XSS简单介绍 一、反射型 1、漏洞逻辑&#xff1a; 为什么有些标签可以触发&#xff0c;有些标签不能触发 可以触发的标签 不能触发的标签 为什么某些标签能触发而某些不能 二、DOM型 1、Ma Spaghet! 要求&#xff1a; 分析&#xff1a; 结果&#xff1a; 2、J…

Unity项目优化记录

背景&#xff1a;测试反馈项目组游戏存在内存泄露&#xff0c;来找到中台这边协调排查。好家伙&#xff0c;跑了两次看了内存快照&#xff0c;再看资源组织和管理方式&#xff0c;存在的问题确实比较多。 1、修复内存泄露&#xff1a;结算界面由于资源引用丢失导致整个面板不会…

44.【C语言】指针(重难点)(G)

目录 19.字符指针变量 *定义 *简单说明 *如果是字符串 *像数组一样指定访问常量字符串的字符 *练习 20.数组指针变量 *定义 *格式 *例子 问题1 问题2 *利用指针打印 21.二维数组传参的本质 *回顾 往期推荐 19.字符指针变量 *定义 指向字符的指针变量&#xff0c;用于存储字符…

使用Python实现B站自动答题机器人

文章目录 1. 写在前面2. 接口分析3. 点选验证分析4. Python程序实现 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长…

什么是OpenTiny?

OpenTiny 是一套企业级的 Web 前端开发解决方案&#xff0c;提供跨端、跨框架的 UI 组件库和低代码引擎&#xff0c;帮助开发者高效构建 Web 应用 。企业运用开发中&#xff0c;可以利用 OpenTiny 的以下核心组件和优势&#xff1a; TinyVue 组件库&#xff1a;一个丰富的组件库…

C/C++实现蓝屏2.0

&#x1f680;欢迎互三&#x1f449;&#xff1a;程序猿方梓燚 &#x1f48e;&#x1f48e; &#x1f680;关注博主&#xff0c;后期持续更新系列文章 &#x1f680;如果有错误感谢请大家批评指出&#xff0c;及时修改 &#x1f680;感谢大家点赞&#x1f44d;收藏⭐评论✍ 前…

【机器学习-监督学习】逻辑斯谛回归

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;…

使用Python制作贪吃蛇小游戏

引言 贪吃蛇游戏是一款经典的电子游戏&#xff0c;玩家通过控制一条不断增长的蛇在格子内移动&#xff0c;并吃掉随机出现的食物来获得分数。随着分数的增加&#xff0c;蛇的身体也会越来越长&#xff0c;游戏的难度也随之提升。在本文中&#xff0c;我们将详细介绍如何使用Py…

基于django的双选宠物托管服务平台/python宠物托管系统

摘 要 伴随着社会以及科学技术的发展&#xff0c;互联网已经渗透在人们的身边&#xff0c;网络慢慢的变成了人们的生活必不可少的一部分&#xff0c;紧接着网络飞速的发展&#xff0c;系统管理这一名词已不陌生&#xff0c;越来越多的双选宠物托管服务等机构都会定制一款属于…

使用 AWS CLI 自动在 Amazon EC2 实例上部署 Apache Web 服务器

“使用 AWS CLI 节省时间” 欢迎来到雲闪世界。今天&#xff0c;我们将利用 AWS CLI 的实际用途来提高效率并自动执行在 Amazon EC2 实例上部署 Apache Web 服务器的步骤。完成“使用 AWS CLI 节省时间”任务后&#xff0c;最后有一个非常有趣的秘密步骤&#xff0c;敬请…

UCOSIII内存管理机制详解

目录 前言 1. 内存管理概述 2. 内存区域&#xff08;存储区&#xff09;和内存块 3. 存储区控制块&#xff08;OS_MEM&#xff09; 4. 内存管理函数 5. 内存碎片问题 6. 注意事项 7.代码实现 7.1创建内存区域 7.2申请内存 7.3释放内存 前言 UCOSIII&#xff08;即Mi…

c++----简单了解string

大家好&#xff0c;也是好久没有更新了。今天我想与大家分享的是c中常用的便捷的应该库。哈哈。可能大家对我们c的便捷性已经在前面有很多耳闻了。比如我们前面说的类模板。也是很便捷的。但是我们今天这个更加方便了。但缺点就是太多了。经过多年的迭代更新。这个库函数已经很…

2024.8.15(python管理mysql、Mycat实现读写分离)

一、python管理mysql 1、搭建主mysql [rootmysql57 ~]# tar -xf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz [rootmysql57 ~]# cp -r mysql-5.7.44-linux-glibc2.12-x86_64 /usr/local/mysql [rootmysql57 ~]# rm -rf /etc/my.cnf [rootmysql57 ~]# mkdir /usr/local/mysql…

qt-13 进度条(模态和非模态)

进度条-模态和非模态 progressdlg.hprogressdlg.cppmain.cpp运行图模态非模态 progressdlg.h #ifndef PROGRESSDLG_H #define PROGRESSDLG_H#include <QDialog> #include <QLabel> #include <QLineEdit> #include <QProgressBar> #include <QCombo…

[书生大模型实战营][L0][Task2] Python 开发前置知识

0. 任务&#xff1a;在 InternStudio 环境中实现功能&#xff1a; python 实现 wordcount函数&#xff0c;统计英文字符串单词的使用频率&#xff0c;并返回字典&#xff1b;vscode 远程调试 InternStudio 中的 python 代码 1. wordcount 函数实现 string.punctuation 是一个…

一键切换全球优质Linux 系统软件源及 Docker 源,轻松安装 Docker —— 适配广泛、零门槛、超强功能的开源脚本!

概述 linuxMirrors开源脚本为 GNU/Linux 系统用户提供了强大的工具,帮助用户轻松更换系统软件源并安装 Docker。脚本适配了多种国内外镜像站,经过测试具备良好的下载速度和 IPv6 兼容性,并且还包括了中国大陆教育网镜像站的选项。无需技术背景,文档提供了详尽的操作指引和常…

机器学习(3)-- 一元线性回归

文章目录 线性回归训练模型测试模型线性回归方程测试实用性 总结 线性回归 线性回归算法是一种用于预测一个或多个自变量&#xff08;解释变量&#xff09;与因变量&#xff08;响应变量&#xff09;之间关系的统计方法。这种方法基于线性假设&#xff0c;即因变量是自变量的线…

【网络安全】重置密码token泄露,实现账户接管

未经许可&#xff0c;不得转载。 文章目录 正文 正文 对某站点测试过程中&#xff0c;登录账户触发忘记密码功能点&#xff0c;其接口、请求及响应如下&#xff1a; PUT /api/v1/people/forgot_password 可以看到&#xff0c;重置密码token和密码哈希均在响应中泄露。 删除co…

【C#】虚部与实部

实数是数学中的一个基本概念&#xff0c;它包括了所有的有理数和无理数。实数集合是连续的&#xff0c;可以表示为数轴上的每一个点。 复数是实数的扩展&#xff0c;它允许进行除零以外的所有基本算术运算。复数由两部分组成&#xff1a;实部和虚部。 实部&#xff08;Real P…