日志系统项目——准备工作了解类的设计模式如单例模式、工厂模式、代理模式

1.六大原则

1.1 单一职责原则

        类的职责应该单⼀,⼀个⽅法只做⼀件事。职责划分清晰了,每次改动到最⼩单位的⽅法或 类。

        使⽤建议:两个完全不⼀样的功能不应该放⼀个类中,⼀个类中应该是⼀组相关性很⾼的函 数、数据的封装

        ⽤例:⽹络聊天:⽹络通信 & 聊天,应该分割成为⽹络通信类 & 聊天类

1.2 开闭原则

        对扩展开放,对修改封闭

        使⽤建议:对软件实体的改动,最好⽤扩展⽽⾮修改的⽅式。

        ⽤例:超时卖货:商品价格---不是修改商品的原来价格,⽽是新增促销价格。

1.3 里氏替换原则

        通俗点讲,就是只要⽗类能出现的地⽅,⼦类就可以出现,⽽且替换为⼦类也不会产⽣任何错 误或异常。

        在继承类时,务必重写⽗类中所有的⽅法,尤其需要注意⽗类的protected⽅法,⼦类尽量不要暴露⾃⼰的public⽅法供外界调⽤。

        使⽤建议:⼦类必须完全实现⽗类的⽅法,孩⼦类可以有⾃⼰的个性。覆盖或实现⽗类的⽅法 时,输⼊参数可以被放⼤,输出可以缩⼩

        ⽤例:跑步运动员类-会跑步,⼦类⻓跑运动员-会跑步且擅⻓⻓跑, ⼦类短跑运动员-会跑步且擅⻓短跑

1.4 依赖倒置原则

        ⾼层模块不应该依赖低层模块,两者都应该依赖其抽象. 不可分割的原⼦逻辑就是低层模式,原⼦逻辑组装成的就是⾼层模块。

        模块间依赖通过抽象(接⼝)发⽣,具体类之间不直接依赖

        使⽤建议:每个类都尽量有抽象类,任何类都不应该从具体类派⽣。尽量不要重写基类的⽅ 法。结合⾥⽒替换原则使⽤。

        ⽤例:奔驰⻋司机类--只能开奔驰; 司机类 -- 给什么⻋,就开什么⻋; 开⻋的⼈:司机--依 赖于抽象

1.5 迪米特原则

        尽量减少对象之间的交互,从⽽减⼩类之间的耦合。⼀个对象应该对其他对象有最少的了解。

        对类的低耦合提出了明确的要求: 只和直接的朋友交流, 朋友之间也是有距离的。⾃⼰的就是⾃⼰的(如果⼀个⽅法放在本类 中,既不增加类间关系,也对本类不产⽣负⾯影响,那就放置在本类中)。

        ⽤例:⽼师让班⻓点名--⽼师给班⻓⼀个名单,班⻓完成点名勾选,返回结果,⽽不是班⻓点 名,⽼师勾选

1.6 接口隔离原则

        客⼾端不应该依赖它不需要的接⼝,类间的依赖关系应该建⽴在最⼩的接⼝上

        使⽤建议:接⼝设计尽量精简单⼀,但是不要对外暴露没有实际意义的接⼝。

        ⽤例:修改密码,不应该提供修改⽤⼾信息接⼝,⽽就是单⼀的最⼩修改密码接⼝,更不要暴 露数据库操作

        从整体上来理解六⼤设计原则,可以简要的概括为⼀句话,⽤抽象构建框架,⽤实现扩展细节,具体 到每⼀条设计原则,则对应⼀条注意事项:

        单⼀职责原则告诉我们实现类要职责单⼀;

        ⾥⽒替换原则告诉我们不要破坏继承体系;

        依赖倒置原则告诉我们要⾯向接⼝编程;

        接口隔离原则告诉我们在设计接口时要精简单一

        迪米特原则告诉我们要降低类的耦合度

        开闭原则告诉我们要对外开放拓展,关闭修改

2 单例模式

        单例模式:⼀个类只能创建⼀个对象,即单例模式,该设计模式可以保证系统中该类只有⼀个实例,并提供⼀个访问它的全局访问点,该实例被所有程序模块共享。⽐如在某个服务器程序中,该服务器的配置信息 存放在⼀个⽂件中,这些配置数据由⼀个单例对象统⼀读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种⽅式简化了在复杂环境下的配置管理。

2.1 饿汉模式

        饿汉模式: 程序启动时就会创建⼀个唯⼀的实例对象。 因为单例对象已经确定, 所以⽐较适⽤于多线程环境中, 多线程获取单例对象不需要加锁, 可以有效的避免资源竞争, 提⾼性能。

//饿汉模式
template<class T>
class server{private:server(){};~server(){};public:server(const server&) = delete;server& operator=(const server&) = delete;server& getinstens(){return _etc;}private:static server<T> _etc;
};template<class T>
server<T> server<T>::_etc;

2.2 懒汉模式

        懒汉模式:第⼀次使⽤要使⽤单例对象的时候创建实例对象。如果单例对象构造特别耗时或者耗费济源(加载插件、加载⽹络资源等), 可以选择懒汉模式, 在第⼀次使⽤的时候才创建对象。

/ 懒汉模式
class Myclient{private:Myclient();~Myclient();public:Myclient(const Myclient&) = delete;Myclient& operator=(const Myclient&) = delete;Myclient* getinsten(){//线程不安全if(_cli == nullptr) _cli = new Myclient();return _cli;}private:static Myclient* _cli;
};

        第一种方法写的懒汉模式明显线程不安全,我们可以通过加锁来让这个过程是线程安全的但是会增加额外的开销,这里并不提倡这种加锁的方式,我们这里采用Effective C++中提供的一个方式

Myclient* Myclient::_cli = nullptr;
template<class T>
class Myclient {
private:Myclient() {}~Myclient() {}public:Myclient(const Myclient&) = delete;Myclient& operator=(const Myclient&) = delete;static Myclient<T>& getInstance() {static Myclient<T> instance_;return instance_;}
};

3 工厂模式

        ⼯⼚模式是⼀种创建型设计模式, 它提供了⼀种创建对象的最佳⽅式。在⼯⼚模式中,我们创建对象 时不会对上层暴露创建逻辑,⽽是通过使⽤⼀个共同结构来指向新创建的对象,以此实现创建-使⽤的分离。

3.1 简单工厂模式

        简单⼯⼚模式: 简单⼯⼚模式实现由⼀个⼯⼚对象通过类型决定创建出来指定产品类的实例。假设有个⼯⼚能⽣产出⽔果,当客⼾需要产品的时候明确告知⼯⼚⽣产哪类⽔果,⼯⼚需要接收⽤⼾提供的类别信息,当新增产品的时候,⼯⼚内部去添加新产品的⽣产⽅式。

#include <iostream>
#include <string>
#include <memory>
class Fruit
{
public:Fruit() {}virtual void show() = 0;
};
class Apple : public Fruit
{
public:Apple() {}virtual void show(){std::cout << "我是⼀个苹果" << std::endl;}
};
class Banana : public Fruit
{
public:Banana() {}virtual void show(){std::cout << "我是⼀个⾹蕉" << std::endl;}
};
class FruitFactory
{
public:static std::shared_ptr<Fruit> create(const std::string &name){if (name == "苹果"){return std::make_shared<Apple>();}else if (name == "⾹蕉"){return std::make_shared<Banana>();}return std::shared_ptr<Fruit>();}
};
int main()
{std::shared_ptr<Fruit> fruit = FruitFactory::create("苹果");fruit->show();fruit = FruitFactory::create("⾹蕉");fruit->show();return 0;
}

        这个模式的结构和管理产品对象的⽅式⼗分简单, 但是它的扩展性⾮常差,当我们需要新增产品的时候,就需要去修改⼯⼚类新增⼀个类型的产品创建逻辑,违背了开闭原则。

3.2 工厂方法模式

        ⼯⼚⽅法模式: 在简单⼯⼚模式下新增多个⼯⼚,多个产品,每个产品对应⼀个⼯⼚。假设现在有A、B 两种产品,则开两个⼯⼚,⼯⼚ A 负责⽣产产品 A,⼯⼚ B 负责⽣产产品 B,⽤⼾只知道产品的⼯⼚名,⽽不知道具体的产品信息,⼯⼚不需要再接收客⼾的产品类别,⽽只负责⽣产产品。

#include <iostream>
#include <string>
#include <memory>
class Fruit
{
public:Fruit() {}virtual void show() = 0;
};
class Apple : public Fruit
{
public:Apple() {}virtual void show(){std::cout << "我是⼀个苹果" << std::endl;}private:std::string _color;
};
class Banana : public Fruit
{
public:Banana() {}virtual void show(){std::cout << "我是⼀个⾹蕉" << std::endl;}
};
class FruitFactory
{
public:virtual std::shared_ptr<Fruit> create() = 0;
};
class AppleFactory : public FruitFactory
{
public:virtual std::shared_ptr<Fruit> create(){return std::make_shared<Apple>();}
};
class BananaFactory : public FruitFactory
{
public:virtual std::shared_ptr<Fruit> create(){return std::make_shared<Banana>();}
};int main()
{std::shared_ptr<FruitFactory> factory(new AppleFactory());std::shared_ptr<Fruit> fruit = factory->create();fruit->show();factory.reset(new BananaFactory());std::shared_ptr<Fruit> fruit2 = factory->create();fruit2->show();return 0;
}

        ⼯⼚⽅法模式每次增加⼀个产品时,都需要增加⼀个具体产品类和⼯⼚类,这会使得系统中类的个数成倍增加,在⼀定程度上增加了系统的耦合度

3.3 抽象工厂模式

        抽象⼯⼚模式: ⼯⼚⽅法模式通过引⼊⼯⼚等级结构,解决了简单⼯⼚模式中⼯⼚类职责太重的问题,但由于⼯⼚⽅法模式中的每个⼯⼚只⽣产⼀类产品,可能会导致系统中存在⼤量的⼯⼚类,势必会增加系统的开销。此时,我们可以考虑将⼀些相关的产品组成⼀个产品族(位于不同产品等级结构中功能相关联的产品组成的家族),由同⼀个⼯⼚来统⼀⽣产,这就是抽象⼯⼚模式的基本思想。

#include <iostream>
#include <string>
#include <memory>
// 抽象⼯⼚:围绕⼀个超级⼯⼚创建其他⼯⼚。每个⽣成的⼯⼚按照⼯⼚模式提供对象。
//  思想:将⼯⼚抽象成两层,抽象⼯⼚ & 具体⼯⼚⼦类, 在⼯⼚⼦类种⽣产不同类型的⼦产品
class Fruit
{
public:Fruit() {}virtual void show() = 0;
};
class Apple : public Fruit
{
public:Apple() {}virtual void show(){std::cout << "我是⼀个苹果" << std::endl;}private:std::string _color;
};
class Banana : public Fruit
{
public:Banana() {}virtual void show(){std::cout << "我是⼀个⾹蕉" << std::endl;}
};class Animal
{
public:virtual void voice() = 0;
};
class Lamp : public Animal
{
public:void voice() { std::cout << "咩咩咩\n"; }
};
class Dog : public Animal
{
public:void voice() { std::cout << "汪汪汪\n"; }
};class Factory
{
public:virtual std::shared_ptr<Fruit> getFruit(const std::string &name) = 0;virtual std::shared_ptr<Animal> getAnimal(const std::string &name) = 0;
};class FruitFactory : public Factory
{
public:virtual std::shared_ptr<Animal> getAnimal(const std::string &name){return std::shared_ptr<Animal>();}virtual std::shared_ptr<Fruit> getFruit(const std::string &name){if (name == "苹果"){return std::make_shared<Apple>();}else if (name == "⾹蕉"){return std::make_shared<Banana>();}return std::shared_ptr<Fruit>();}
};class AnimalFactory : public Factory
{
public:virtual std::shared_ptr<Fruit> getFruit(const std::string &name){return std::shared_ptr<Fruit>();}virtual std::shared_ptr<Animal> getAnimal(const std::string &name){if (name == "⼩⽺"){return std::make_shared<Lamp>();}else if (name == "⼩狗"){return std::make_shared<Dog>();}return std::shared_ptr<Animal>();}
};
class FactoryProducer
{
public:static std::shared_ptr<Factory> getFactory(const std::string &name){if (name == "动物"){return std::make_shared<AnimalFactory>();}else{return std::make_shared<FruitFactory>();}}
};

        抽象⼯⼚模式适⽤于⽣产多个⼯⼚系列产品衍⽣的设计模式,增加新的产品等级结构复杂,需要对原有系统进⾏较⼤的修改,甚⾄需要修改抽象层代码,违背了“开闭原则”。

4. 建造者模式

        建造者模式:建造者模式是⼀种创建型设计模式, 使⽤多个简单的对象⼀步⼀步构建成⼀个复杂的对象,能够将⼀个复杂的对象的构建与它的表⽰分离,提供⼀种创建对象的最佳⽅式。主要⽤于解决对象的构建过于复杂的问题。

建造者模式主要基于五个核⼼类实现:

抽象产品类

具体产品类:⼀个具体的产品对象类

抽象Builder类:创建⼀个产品对象所需的各个部件的抽象接⼝

具体产品的Builder类:实现抽象接⼝,构建各个部件

指挥者Director类:统⼀组建过程,提供给调⽤者使⽤,通过指挥者来构造产品

#include <iostream>
#include <memory>
/*抽象电脑类*/
class Computer
{
public:using ptr = std::shared_ptr<Computer>;Computer() {}void setBoard(const std::string &board) { _board = board; }void setDisplay(const std::string &display) { _display = display; }virtual void setOs() = 0;std::string toString(){std::string computer = "Computer:{\n";computer += "\tboard=" + _board + ",\n";computer += "\tdisplay=" + _display + ",\n";computer += "\tOs=" + _os + ",\n";computer += "}\n";return computer;}protected:std::string _board;std::string _display;std::string _os;
};
/*具体产品类*/
class MacBook : public Computer
{
public:using ptr = std::shared_ptr<MacBook>;MacBook() {}virtual void setOs(){_os = "Max Os X12";}
};
/*抽象建造者类:包含创建⼀个产品对象的各个部件的抽象接⼝*/
class Builder
{
public:using ptr = std::shared_ptr<Builder>;virtual void buildBoard(const std::string &board) = 0;virtual void buildDisplay(const std::string &display) = 0;virtual void buildOs() = 0;virtual Computer::ptr build() = 0;
};/*具体产品的具体建造者类:实现抽象接⼝,构建和组装各个部件*/
class MacBookBuilder : public Builder
{
public:using ptr = std::shared_ptr<MacBookBuilder>;MacBookBuilder() : _computer(new MacBook()) {}virtual void buildBoard(const std::string &board){_computer->setBoard(board);}virtual void buildDisplay(const std::string &display){_computer->setDisplay(display);}virtual void buildOs(){_computer->setOs();}virtual Computer::ptr build(){return _computer;}private:Computer::ptr _computer;
};/*指挥者类,提供给调⽤者使⽤,通过指挥者来构造复杂产品*/
class Director
{
public:Director(Builder *builder) : _builder(builder) {}void construct(const std::string &board, const std::string &display){_builder->buildBoard(board);_builder->buildDisplay(display);_builder->buildOs();}private:Builder::ptr _builder;
};

5.代理模式

        代理模式指代理控制对其他对象的访问, 也就是代理对象控制对原对象的引⽤。在某些情况下,⼀个对象不适合或者不能直接被引⽤访问,⽽代理对象可以在客⼾端和⽬标对象之间起到中介的作⽤。

代理模式的结构包括⼀个是真正的你要访问的对象(⽬标类)、⼀个是代理对象。⽬标对象与代理对象实现同⼀个接⼝,先访问代理类再通过代理类访问⽬标对象。代理模式分为静态代理、动态代理:

        静态代理指的是,在编译时就已经确定好了代理类和被代理类的关系。也就是说,在编译时就已经

确定了代理类要代理的是哪个被代理类。

        动态代理指的是,在运⾏时才动态⽣成代理类,并将其与被代理类绑定。这意味着,在运⾏时才能确定代理类要代理的是哪个被代理类。

        以租房为例,房东将房⼦租出去,但是要租房⼦出去,需要发布招租启⽰, 带⼈看房,负责维修,这些⼯作中有些操作并⾮房东能完成,因此房东为了图省事,将房⼦委托给中介进⾏租赁。 代理模式实现:

/*房东要把⼀个房⼦通过中介租出去理解代理模式*/
#include <iostream>
#include <string>
class RentHouse
{
public:virtual void rentHouse() = 0;
};
/*房东类:将房⼦租出去*/
class Landlord : public RentHouse
{
public:void rentHouse(){std::cout << "将房⼦租出去\n";}
};
/*中介代理类:对租房⼦进⾏功能加强,实现租房以外的其他功能*/
class Intermediary : public RentHouse
{
public:void rentHouse(){std::cout << "发布招租启⽰\n";std::cout << "带⼈看房\n";_landlord.rentHouse();std::cout << "负责租后维修\n";}private:Landlord _landlord;
};
int main()
{Intermediary intermediary;intermediary.rentHouse();return 0;
}

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

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

相关文章

股指期货基差怎么计算?公式介绍

先说说啥是基差。简单来说&#xff0c;基差就是股指期货价格和现货指数价格之间的差值。就好比你手里有一张股票指数的“未来提货券”&#xff08;股指期货&#xff09;&#xff0c;但你现在就能买到股票指数&#xff08;现货指数&#xff09;&#xff0c;这两者之间的价格差&a…

Comfyui 与 SDwebui

ComfyUI和SD WebUI是基于Stable Diffusion模型的两种不同用户界面工具&#xff0c;它们在功能、用户体验和适用场景上各有优劣。 1. 功能与灵活性 ComfyUI&#xff1a;ComfyUI以其节点式工作流设计为核心&#xff0c;强调用户自定义和灵活性。用户可以通过连接不同的模块&…

深圳传音控股手机软件开发岗内推

1.负责手机UI、功能开发 2.负责手机具体模块(通信、多媒体、系统、应用)独立开发 3.负责手机软件调试、log分析等 推荐码&#xff1a;EVHPB3 &#xff0c;简历第一时间送到HR面前&#xff5e;

never_give_up

一个很有意思的题&#xff1a; never_give_up - Bugku CTF平台 注意到注释里面有1p.html&#xff0c;我们直接在源代码界面看&#xff0c;这样就不会跳转到它那个链接的&#xff1a; 然后解码可得&#xff1a; ";if(!$_GET[id]) {header(Location: hello.php?id1);exi…

Aliyun CTF 2025 web 复现

文章目录 ezoj打卡OKoffens1veFakejump server ezoj 进来一看是算法题&#xff0c;先做了试试看,gpt写了一个高效代码通过了 通过后没看见啥&#xff0c;根据页面底部提示去/source看到源代码&#xff0c;没啥思路&#xff0c;直接看wp吧&#xff0c;跟算法题没啥关系,关键是去…

BigFoot EventAlertMod lua

BigFoot EventAlertMod lua脚本插件&#xff0c;追踪当前目标的DOT&#xff0c;自身的HOT&#xff0c;持续时间监控 D:\Battle.net\World of Warcraft\_classic_\Interface\AddOns\EventAlertMod 想知道技能的ID&#xff0c;执行命令如下&#xff1a;本例子为“神圣牺牲” /e…

ICLR 2025|DAMO开发者矩阵合作专场

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; AITIME 01 ICLR 2025预讲会合作专场 AITIME 02 专场信息 01 Dynamic Diffusion Transformer 讲者&#xff1a;赵望博&#xff0c;达摩院研究型实习生 时间&#xff1a;3月12日 19:00-19:15 报告简介&#xff1a…

解决jsch远程sftp连接报错:Exception:Algorithm negotiation fail

问题背景 今天遇见了使用JSch连接服务器时&#xff0c;报错Exception:Algorithm negotiation fail的问题&#xff01;研究了半天哇&#xff01;终于解决啦&#xff01;把解决方案在这里给大家共享一下子&#xff01; 问题原因 问题原因在于&#xff0c;JSch所支持的加密算法…

【C++】C++11新特性

目录 列表初始化 左值与右值 左值引用和右值引用 移动构造和移动赋值 类型推导 lambda 捕捉列表 函数对象及绑定 bind函数 包装器 Args参数包 抛异常 列表初始化 在C11中一切皆可用列表初始化。 用法&#xff1a;直接在变量名后面加上初始化列表进行初始化 cl…

FreeBSD下安装npm Node.js的22版本 并简单测试js服务器

FreeBSD下安装Node.js 在FreeBSD下安装Node.js很方便&#xff0c;直接pkg安装即可。 使用pkg install安装npm sudo pkg install npm-node22 Updating FreeBSD repository catalogue... Fetching data.pkg: 100% 7 MiB 2.5MB/s 00:03 Processing entries: 100% FreeB…

云原生可观测性体系:数字世界的神经感知网络

引言&#xff1a;从监控到全景式观测的范式升级 Datadog每日处理百万亿指标&#xff0c;Elastic APM实现万级服务拓扑动态发现。Grafana Loki日志分析延迟降至200ms内&#xff0c;Prometheus单集群支持千万时序存储。Uber通过全链路追踪压缩故障定位时间至秒级&#xff0c;Net…

基于VMware的Ubuntu22.04系统安装和配置以及解决Ubuntu共享文件夹无法实现的问题

一、前期准备 本次安装的虚拟机软件是 VMware Workstation Pro 17 登录跳转到 所有产品 进行下载 ​​​跳转到下载页面​​​ 选择 Windows 产品进行安装 勾选协议同意下载 离线版提供&#xff1a;大家根据自己电脑版本配置进行选择下载 本篇使用的虚拟机版本为 VMware Wor…

线程同步与互斥

目录 资源共享问题 &#xff08;一&#xff09;临界资源与临界区 &#xff08;二&#xff09;多线程并发访问问题 &#xff08;三&#xff09;锁 互斥锁原理 加锁原理 解锁原理 互斥锁相关操作接口 互斥锁封装 死锁 死锁产生的四个必要条件 解决死锁方法 &#xff…

SpringMVC 基本概念与代码示例

1. SpringMVC 简介 SpringMVC 是 Spring 框架中的一个 Web 层框架&#xff0c;基于 MVC&#xff08;Model-View-Controller&#xff09; 设计模式&#xff0c;提供了清晰的分层结构&#xff0c;适用于 Web 应用开发 SpringMVC 主要组件 DispatcherServlet&#xff08;前端控…

Banana Pi OpenWRT One Wifi6 OpenWrt社区官方开源路由器评测

第一款不可破解、开源、版权软件、符合 FCC、CE 和 RoHS 的维修权路由器 OpenWRT项目今年已经20岁了&#xff0c;为了纪念这一时刻&#xff0c;Banana Pi OpenWrt One/AP-24.XY路由器开发系统已经上市。这是OpenWRT团队与硬件公司的第一个联合项目。选择 Banana Pi&#xff0c;…

打造智能钉钉机器人:借助智谱GLM-4-Flash实现高效智能回复(文末附源码)

文章目录 前言一、准备工作&#xff08;一&#xff09;钉钉机器人&#xff08;二&#xff09;智谱 GLM-4-Flash&#xff08;三&#xff09;内网穿透工具 cpolar&#xff08;四&#xff09;需要准备的工具和环境 二、钉钉机器人的创建与配置步骤1&#xff1a;创建钉钉机器人步骤…

react基础语法视图层类组件

react基础语法视图层&类组件 MVVM *区别mvc&mvvm 两者的区别&#xff1a; 数据模型去渲染视图。数据层改了&#xff0c;vue自己会监听到帮我们拿最新的数据去渲染视图&#xff1b;构建数据构建视图&#xff0c;数据驱动的思想。这一套是非常相似的。 视图中的内容改变&…

数据结构--【顺序表与链表】笔记

顺序表 template <class T> class arrList :public List<T> //表示 arrList 类以公有继承的方式继承自 List<T> 类 //公有继承意味着 List<T> 类的公共成员在 arrList 类中仍然是公共成员&#xff0c;受保护成员在 arrList 类中仍然是受保护成员。 { …

Docker容器与宿主机目录映射深度解析

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 一、Docker容器与宿主机目录映射基础原理 在深入了解如何查询 Docker 容器目录在宿主机的映射目录之前&#xff0c;有必要先明晰其背后的基础原理。Docker 容器通过挂载&#xff08;mount&#xff09;机制将宿主机的…

p5.js:模拟 n个彩色小球在一个3D大球体内部弹跳

向 豆包 提问&#xff1a;编写一个 p5.js 脚本&#xff0c;模拟 42 个彩色小球在一个3D大球体内部弹跳。每个小球都应留下一条逐渐消失的轨迹。大球体应缓慢旋转&#xff0c;并显示透明的轮廓线。请确保实现适当的碰撞检测&#xff0c;使小球保持在球体内部。 cd p5-demo copy…