PaQiuQiu
大家好,我是某AI赛道头部企业算法总监,欢迎来到我的CSDN个人主页!作为一个热衷于技术的从业者,我在这里与大家分享最新的科技动态、独到的技术观点和实践经验。
展开
-
教练,我想学设计之禅
本专栏分四部分展开,设计模式与设计原则、算法与数据结构、架构设计以及实战为王。原创 2023-01-25 09:30:41 · 919 阅读 · 0 评论 -
设计模式之兼容不同厂家的相机
仔细看上面的代码,会发现一个问题,每一个实例工厂负责生产一个实例产品,也就是一个产品对应一个工厂,一个工厂对应一个产品,那么小米不仅仅生产相机,还生产耳机,智能手环,智能插座等等相关的小米产品簇,不可能给这每一个产品都创建一个工厂类,那样的话代码中的类就太多了,不好维护,而且也不符合实际情况。实际上小米或者华为的工厂里面,有相关联的产品簇都是在一个工厂完成创建的;写完后,初级程序员恍然大悟,抽象工厂模式把一个产品簇的产品放在一个工厂类中去创建,不仅大大减少了工厂类的个数,更符合现实中工厂生产产品的模式。原创 2024-02-24 16:13:06 · 405 阅读 · 0 评论 -
构建自己的插件框架:第 4 部分
一个精心设计的C++ 包装类(由应用程序提供给插件开发者)会把C插件封装起来,将每一个非基本数据类型的C 参数包装成相应的C++ 类型,调用由插件对象实现的C++ 函数。我们将从分析现有插件/组件系统开始,一步步深入了解如何开发插件框架,以及很多需要注意的问题,比如二进制兼容性等,在文章的最后,我们将给出一个比较合理的解决方案。包装类对象保存其C 接口指针,在其函数的实现中,将对包装对象的函数调用直接转发给内部的C 接口指针,然后如果需要的话,还得再将返回结果进行包装。对于某些对象,这么做是可以的。原创 2023-11-09 20:46:33 · 113 阅读 · 0 评论 -
构建自己的插件框架:第 5 部分
这个插件框架相对于其他已有的系统具有一些独特的属性,并且灵活易用,兼顾C 和C++,提供多种部署方式(动态库和静态库)。然后,所有人都会忘记C,只需要扩展应用系统提供的顶层的对象模型来编写插件——这些都是使用C++ 编写的。正如你看到的那样,我们的游戏实在是太简单了。我们将从分析现有插件/组件系统开始,一步步深入了解如何开发插件框架,以及很多需要注意的问题,比如二进制兼容性等,在文章的最后,我们将给出一个比较合理的解决方案。的形式传入,经过处理后,其中的所有动态插件都被加载进来,静态插件则显式初始化。原创 2023-11-09 20:50:27 · 117 阅读 · 0 评论 -
构建自己的插件框架:第 3 部分
对于一些应用程序而言,这些都不是问题,因为它们不会涉及到32 位的限制(如果是使用无符号整数,则是31 位),但是如果你需要在64 位系统序列化你的对象,又要在32 位系统上反序列化,那么你就得注意这个问题了。这里,我们从设计模式的角度来重构我们的简单的游戏,不过,对于你自己的业务模型,你必须自己动手了。但是,使用单一的类来处理插件的交互更为合适。我们将从分析现有插件/组件系统开始,一步步深入了解如何开发插件框架,以及很多需要注意的问题,比如二进制兼容性等,在文章的最后,我们将给出一个比较合理的解决方案。原创 2023-11-03 08:00:57 · 100 阅读 · 0 评论 -
构建自己的插件框架:第 2 部分
这种设计允许程序拥有充分的灵活性,插件可以尝试注册同一对象类型的多种版本,以便在兼容旧版本的情况下使用新接口的优点。我们将从分析现有插件/组件系统开始,一步步深入了解如何开发插件框架,以及很多需要注意的问题,比如二进制兼容性等,在文章的最后,我们将给出一个比较合理的解决方案。是一个通用版本,但是我们也会探讨,如何将一个通用设计的插件管理器转换成特定系统的。需要注意的是,插件框架提供了所有必须的基础接口,用于将C 对象适配成C++ 对象,但是仍然需要应用程序的帮助,因为它并不知道自己需要适配的对象类型。原创 2023-10-31 20:47:36 · 114 阅读 · 0 评论 -
构建自己的插件框架:第 1 部分
最基本的方式是定义一个接口,提供一系列插件(动态的或者是静态)需要暴露出的函数。这种实现从技术上说是可行的,但实际并不那么简单地操作。原因在于,一个插件需要支持两类接口,但是却只能暴露出一个接口的函数集。这意味着,两类接口必须混合在一起。第一个接口(协议)是通用插件接口。该接口允许中心系统初始化插件,能够将插件提供的用于创建、销毁对象的函数注册给中心系统。这个通用插件接口不是特定领域相关的,因此能够作为一个可复用库。第二个接口则是插件对象提供的功能接口。原创 2023-10-27 20:56:17 · 132 阅读 · 0 评论 -
C++实现高性能内存池(二)
在上面的类设计中可以看到,在这个内存池中,其实是使用链表来管理整个内存池的内存区块的。内存池首先会定义固定大小的基本内存区块(Block),然后在其中定义了一个可以实例化为存放对象内存槽的对象槽(Slot_)和对象槽指针的一个联合。我们知道,对于栈来说,链栈其实并不是最好的实现方式,因为这种结构的栈不可避免的会涉及到指针相关的操作,同时,还会消耗一定量的空间来存放节点之间的指针。事实上,我们可以使用。毫无疑问是整个内存池的关键所在,但实际上理清了整个内存池的设计之后,其实现并不复杂。原创 2023-10-10 21:04:50 · 568 阅读 · 0 评论 -
C++实现高性能内存池(一)
内存池是池化技术中的一种形式。通常我们在编写程序的时候回使用newdelete这些关键字来向操作系统申请内存,而这样造成的后果就是每次申请内存和释放内存的时候,都需要和操作系统的系统调用打交道,从堆中分配所需的内存。如果这样的操作太过频繁,就会找成大量的内存碎片进而降低内存的分配性能,甚至出现内存分配失败的情况。而内存池就是为了解决这个问题而产生的一种技术。原创 2023-10-10 21:02:00 · 263 阅读 · 0 评论 -
生产者-消费者模式
为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库,生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为;而消费者只需要从共享数据区中去获取数据,就不再需要关心生产者的行为。的模式,弄懂生产者-消费者问题能够让我们对并发编程的理解加深。唤醒,唤醒后加锁,要注意的是被唤醒后有可能加锁失败,此时继续阻塞;6)循环判断一下目前的队列情况,对于各自的特殊情况(队满和队空)进行处理。可能因为多线程紊乱的问题,加入了临界区。了,如果后面的条件不满足,也不会解除阻塞。原创 2023-07-31 16:04:56 · 269 阅读 · 0 评论 -
设计模式—“领域规则”
给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。 ——《设计模式》GoF1、模式的应用场合是模式应用中的难点,只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且容易抽象为语法规则的问题”才适合使用模式。2、使用模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法。3、模式比较适合简单的文法表示,对于复杂的文法表示,原创 2023-06-24 14:36:03 · 514 阅读 · 0 评论 -
设计模式—“行为变化”
将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 ——《设计模式》GoF1、Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语音中,常见的实现手段是“将行为抽象为对象”。2、实现Command接口的具体命令对象有时候根据需要可能会保存一些额外的状态信息。通过使用Composite模式,可以将多个“命令”封装为一个“复合命令”。原创 2023-06-22 09:38:57 · 929 阅读 · 0 评论 -
设计模式—“数据结构”
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性(稳定)。 ——《设计模式》GoF1、Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致地(复用)处理对象和对象容器,无需关系处理的是单个的对象,还是组合的对象容器2、将“客户代码与复杂的对象容器结构”解耦是Compostie。原创 2023-06-20 10:53:52 · 947 阅读 · 1 评论 -
设计模式—“状态变化”
允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。 ——《设计模式》GoF1、State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。2、为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的——即要么彻底转换过来,要么不转换。原创 2023-06-19 13:38:13 · 954 阅读 · 0 评论 -
设计模式—“接口隔离”
为子系统中的一组接口提供一个一致(稳定)的界面,Fascade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用(复用) ——《设计模式》GoF1、从客户程序的角度来看,Fascade模式简化了整个组件系统的接口,对于组件内部与外部客户程序来说,达到了一种“解耦”的效果——内部子系统的任何变化不会影响到Fascade接口的变化。2、Fascade设计模式更注重从架构的层次去看整个系统,而不是单个类的层次。Fascade。原创 2023-05-25 18:16:15 · 1185 阅读 · 0 评论 -
设计模式—“对象创建”
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。 ——《设计模式》GoF所谓使一个类的实例化延迟到其子类,是因为抽象的 (工厂) 类不知道要实例化哪个具体 (产品) 类,所以实例化动作只能由具体的子 (工厂) 类去做, 抽象和具体 (工厂) 类中定义的、产生实例 (产品) 的接口函数,被我们成为工厂方法,因为它负责 “生产” 一个对象。原创 2023-05-09 22:39:49 · 611 阅读 · 0 评论 -
设计模式—“单一职责”
动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码&减少子类个数)。 ——《设计模式》GoF1、通过采用组合而非继承的手法,Decorator模式实现了运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。2、Decorator类在接口上表现为的继承关系,即Decorator类继承了Component。原创 2023-03-08 15:16:26 · 205 阅读 · 0 评论 -
设计模式—“组件协作”
定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的某些特定步骤。 ——《设计模式》GoF1、模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。2、除了可以灵活应对子步骤的变化外,“原创 2023-03-06 18:31:03 · 238 阅读 · 0 评论 -
设计模式—“对象性能”
运用共享技术有效地支持大量细粒度的对象。 ——《设计模式》GoF1、面向对象很好地解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。2、Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。原创 2023-02-20 13:29:12 · 391 阅读 · 0 评论 -
依赖倒置原则|SOLID as a rock
*高层模块:**描述本质上更抽象并包含更复杂的逻辑的操作。这些模块在我们的应用程序中编排低层模块。**低层模块:**描述更具体和个性化的实现,专注于应用程序的细节和较小的部分,这些模块在高级模块中使用。如您所见,我们选取了一个基本的代码示例,并将其转换为可重用、灵活和模块化的代码段。喜欢这篇文章吗☝️?原创 2023-02-11 16:32:23 · 489 阅读 · 0 评论 -
接口隔离原则|SOLID as a rock
我也认为自己是一个务实的人,希望以尽可能简单的方式而不是标准方式或使用行话来传达想法。对于一些编译语言(如以编译缓慢而闻名的C++)来说,这是一个重要的方面,而另一种方式是不言自明的。尽管大型接口是一个潜在的问题,但ISP与接口的大小无关。它的真正含义是,您应该始终以这样一种方式设计抽象,即客户端不应该依赖他们不用的方法。Martin 还提到,“胖接口”——带有其他无用方法的接口——会导致类之间的无意耦合。当您通过确定参与您的领域的主要角色来分解问题时,这个原则会自然而然地出现。原创 2023-02-11 15:19:43 · 397 阅读 · 0 评论 -
里氏替换原则|SOLID as a rock
所以你经常看到我不使用诸如 override、final、public(在继承时)之类的关键字,只是为了使代码在单一标准屏幕尺寸下紧凑且易于使用(大部分时间)。我也更喜欢 struct 而不是 class 只是为了通过不写“public:”来节省行,有时也会错过虚析构函数、构造函数、复制构造函数、前缀 std::,故意删除动态内存。我也认为自己是一个务实的人,希望以尽可能简单的方式而不是标准方式或使用行话来传达想法。上面的例子清楚地表明了这个原则所追求的,即松耦合和确保正确的继承。提供如此有用的原则。原创 2023-02-11 11:30:05 · 505 阅读 · 0 评论 -
开放封闭原则|SOLID as a rock
请记住类永远不可能完全关闭,总有未曾预见的变化要求类做出改变。但是,如果一个变化是可预见的,比如上文中的filters,那么当那些变化的需求源源不断而来时,这对于你而言是一个绝佳的应用OCP 的机会,为未来做好准备。原创 2023-02-11 10:57:55 · 443 阅读 · 0 评论 -
单一职责原则|SOLID as a rock
所以你经常看到我不使用诸如 override、final、public(在继承时)之类的关键字,只是为了使代码在单一标准屏幕尺寸下紧凑且易于使用(大部分时间)。我也更喜欢 struct 而不是 class 只是为了通过不写“public:”来节省行,有时也会错过虚析构函数、构造函数、复制构造函数、前缀 std::,故意删除动态内存。SRP 被广泛应用于重构中代码的修改,这通常是在没有完全理解SRP的情况下完成的,很容易导致代码库的碎片化,并产生一系列负面后果。SOLID 设计原则侧重于开发。原创 2023-02-11 10:11:04 · 443 阅读 · 0 评论 -
面向对象设计原则
为什么要面向对象设计?对于软件开发人员来说,变化是复用的天敌,而。提到这,我们不得不。从宏观层面来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的的影响减为最小1)从微观层面看,面向对象的方式更强调各个类的“责任”2)由于需求变化导致的新增类型不应该影响原来类型的实现1)从语言层面来看,对象封装了代码和数据2)从规格层面讲,对象是一系列可被使用的公共接口3)从概念层面讲,对象是某种拥有责任的抽象作为衡量软件质量优劣的准绳,面向对象的设计原则在其中扮演着关键角色。原创 2023-01-30 22:47:53 · 456 阅读 · 0 评论 -
浅谈设计模式
有变化是好事,至少你的业务正在茁壮成长,业务不断地在进来,为了应该上述的变化,在软件设计时,有经验的开发者都会尽量选择支持未来任何可能变更的方式,做好扩展性,甚至做的更好的,在软件架构方面,都留足了空间,支持架构演进。时代,变化越来越多,在开发过程中,需求的变化是程序员经常需要面对的事情,一般我们都不建议变,但是敏捷提倡变化,互联网行业尤其如此,一个小的变化,也许能带来极大的友好流量。2、向上,深刻把握面向对象机制所带来的抽象意义,理解如何使用这些机制来表达现实世界,掌握什么是“好的面向对象设计”。原创 2023-01-29 17:00:08 · 374 阅读 · 0 评论 -
23种设计模式(二十三)——解释器模式【邻域问题】
在这样的情况下,将这种特定的领域的问题转换表达为某种语法规则的句子。,用来实现语法规则中非终结符相关的操作,通常一个解释器对应一个语法规则,可以包含其他解释器,如果用组合模式构建抽象语法树的话,就。,用来实现语法规则中和终结符相关的操作,不再包含其他的解释器,如果用组合模式来构建抽象语法树的话,就。给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。5、Client:客户端,指的是使用解释器的客户端,通常在这里将按照语言的语法做的表达式。,可以有多种终结符解释器。原创 2023-01-24 18:31:51 · 1178 阅读 · 0 评论 -
23种设计模式(二十二)——访问者模式【行为变化】
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于其内部各个元素的新操作。访问者模式通过在访问者对象中为多个目标类提供相同操作的变体, 让你能在属于不同类的一组对象上执行同一操作。你可将该行为抽取到单独的访问者类中, 只需实现接收相关类的对象作为参数的访问者方法并将其他方法留空即可。该模式会将所有非主要的行为抽取到一组访问者类中, 使得程序的主要类能更专注于主要的工作。5、为每个无法在元素层次结构中实现的行为创建一个具体访问者类并实现所有的访问者方法。原创 2023-01-23 11:04:23 · 1480 阅读 · 0 评论 -
23种设计模式(二十一)——命令模式【行为变化】
服务员看到托盘后对订单进行检查, 确保所有食物都是你要的, 然后将食物放到了你的桌上。使用同样的方式, 你还可以将命令放入队列、 记录命令或者通过网络发送命令。命令模式可以通过抽象或接口类型 (发送者) 中的行为方法来识别, 该类型调用另一个不同的抽象或接口类型 (接收者) 实现中的方法, 该实现则是在创建时由命令模式的实现封装。这一改变也带来了许多有趣的应用: 你可以将命令作为方法的参数进行传递、 将命令保存在其他对象中, 或者在运行时切换已连接的命令等。2、抽取请求并使之成为实现命令接口的具体命令类。原创 2023-01-23 10:41:38 · 1361 阅读 · 0 评论 -
23种设计模式(二十)——责任链模式【数据结构】
将链中的每一个节点看作是一个对象,每个节点处理的请求不同,且内部自动维护一个下一节点对象。当一个请求从链式的首段发出时,会沿着链的路径依此传递给每一个节点对象,直至有对象处理这个请求为止。1、当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式。该模式能将多个处理者连接成一条链。 接收到请求后, 它会 “询问” 每个处理者是否能够对其进行处理。 这样所有处理者都有机会来处理请求。2、当必须按顺序执行多个处理者时, 可以使用该模式。无论你以何种顺序将处理者连接成一条链,原创 2023-01-23 10:01:10 · 1344 阅读 · 0 评论 -
23种设计模式(十九)——迭代器模式【数据结构】
迭代器封装了与复杂数据结构进行交互的细节, 为客户端提供多个访问集合元素的简单方法。这种方式不仅对客户端来说非常方便, 而且能避免客户端在直接与集合交互时执行错误或有害的操作, 从而起到保护集合的作用。1、声明迭代器接口。集合对象必须将自身传递给迭代器的构造函数来创建两者之间的链接。如果你在代码中使用了这些接口, 那么将其他实现了这些接口的集合和迭代器传递给它时, 它仍将可以正常运行。如果你计划拥有多组不同的迭代器, 则可以声明多个类似的方法。使用迭代器的客户端代码可能没有其所遍历的集合的直接访问权限。原创 2023-01-23 09:40:34 · 883 阅读 · 0 评论 -
23种设计模式(十八)——组合模式【数据结构】
有时又叫作整体-部分(Part-Whole)模式,是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性。这将会违反_接口隔离原则_, 因为叶节点类中的这些方法为空。但是, 这可以让客户端无差别地访问所有元素, 即使是组成树状结构的元素。在这一接口的帮助下, 客户端不必在意其所使用的对象的具体类。组合模式在 C++ 代码中很常见, 常用于表示与图形打交道的用户界面组件或代码的层次结构。5、最后, 在容器中定义添加和删除子元素的方法。原创 2023-01-22 16:22:59 · 1397 阅读 · 0 评论 -
23种设计模式(十七)——状态模式【状态变化】
亦称:State。原创 2023-01-22 15:05:46 · 1129 阅读 · 0 评论 -
23种设计模式(十六)——备忘录模式【状态变化】
亦称:调解人、控制器、Intermediary、Controller、Mediator。原创 2023-01-21 11:50:38 · 1368 阅读 · 0 评论 -
23种设计模式(十五)——适配器模式【接口隔离】
不同国家的电源插头和插座标准不同。当适配器的任何方法被调用时, 它会将参数转换为合适的格式, 然后将调用定向到其封装对象中的一个或多个方法。4、在适配器类中添加一个成员变量用于保存对于服务对象的引用。5、依次实现适配器类客户端接口的所有方法。这样一来, 你就可以在不影响客户端代码的情况下修改或扩展适配器。将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器。的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。3、创建遵循客户端接口的适配器类。原创 2023-01-21 10:12:15 · 1629 阅读 · 0 评论 -
23种设计模式(十四)——中介者模式【接口隔离】
6、修改组件代码, 使其可调用中介者的通知方法, 而非其他组件的方法。然后将调用其他组件的代码抽取到中介者类中, 并在中介者接收到该组件通知时执行这些代码。只要组件使用通用接口与其中介者合作, 你就能将该组件与不同实现中的中介者进行连接。2、声明中介者接口并描述中介者和各种组件之间所需的交流接口。5、组件必须保存对于中介者对象的引用。该连接通常在组件的构造函数中建立, 该函数会将中介者对象作为参数传递。2、对象可重用性差:由于一个对象和其他对象具有很强的关联,若没有其他对象的支持,对象很难被重用,原创 2023-01-21 09:05:44 · 1317 阅读 · 0 评论 -
23种设计模式(十三)——代理模式【接口隔离】
1、如果没有现成的服务接口, 你就需要创建一个接口来实现代理和服务对象的可交换性。从服务类中抽取接口并非总是可行的, 因为你需要对服务的所有客户端进行修改, 让它们使用接口。这时我们就可以使用代理模式,通过一个代理对象,在每次使用时才创建对象,在使用完进行销毁。又或者对于自己的核心业务增加保护等等,凡是这种需要对使用的服务增加额外的处理,除了直接修改原有的服务,我们更应该考虑使用代理对象。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。3、根据需求实现代理方法。原创 2023-01-20 16:09:37 · 1515 阅读 · 0 评论 -
23种设计模式(十二)——外观模式【接口隔离】
亦称:Facade。原创 2023-01-20 10:11:57 · 1374 阅读 · 0 评论 -
23种设计模式(十一)——生成器模式【对象创建】
但是, 只有在调用构造步骤的客户端代码可以通过通用接口与建造者进行交互时, 这样的调用才能返回需要的房屋。不要忘记实现获取构造结果对象的方法。你不能在生成器接口中声明该方法, 因为不同生成器构造的产品可能没有公共接口, 因此你就不知道该方法返回的对象类型。在这种情况下, 你可以创建多个不同的生成器, 用不同方式实现一组相同的创建步骤。对于对象的使用者来说,我只需要告诉创建者我需要使用这个复杂对象,至于这个复杂对象是怎么创建的,不关我事。当你需要创建不同形式的产品时, 其中的一些构造步骤可能需要不同的实现。原创 2023-01-19 10:16:56 · 1348 阅读 · 0 评论 -
23种设计模式(十)——原型模式【对象创建】
亦称:克隆、Clone、Prototype。原创 2023-01-19 09:41:41 · 1332 阅读 · 0 评论