设计模式 创建型模式 三 (设计模式创建型模式)
本文目录导航:
设计模式(三)创建型模式
根据菜鸟教程的目录,我们首先来看看创建型模式。
创建型模式研究: 下面分别对创建型模式下的各种具体模式进行讲解。
先看例子: 工厂模式。
某功能的使用者只和接口打交道,不关心如何实现。
这种情况下,肯定有一个接口类,使用者使用接口;功能提供者继承并实现接口。
这利用了C++的多态特性。
既然使用者只关心接口,那么没有必要把子类直接给使用者,没有必要让使用者在代码中直接new子类。
如果这样做,会把不必要的信息暴露给使用者,增加了信息的耦合。
试想,如果使用者在很多地方都new了子类,那么如果这些地方需要修改的话,怎么改?只能一个一个地方改,改完还需要编译,维护极其困难。
工厂模式是指,针对某一功能接口,我们要新建一个工厂类,此工厂类将接口子类名称、接口子类的创建过程封装起来,只返回一个接口指针给接口的使用者。
接口的实现类对使用者完全透明,高度解耦。
这样可以方便地切换接口的具体实现,而不影响上层功能使用者。
拿 汽车 打比方,不管工厂生产 汽车 的流程是什么,只要是 汽车 ,它的驾驶方法(人机接口)都类似。
显而易见,工厂模式在使用者和实现者之间增加了一个封装层,这正印证了计算机行业中一句名言: 典型的例子是:Qt中的数据库模块就利用了工厂模式,封装了数据库的底层实现。
在保持数据库用户接口不变的情况下,通过更换数据库驱动,可以实现数据库类型无缝切换。
在需求趋于稳定时使用,需求不稳定时,不要过度设计,否则设计很容易被推翻,白费力气。
从设计模式的本质来看,工厂模式: 先看例子: 抽象工厂模式。
由前面工厂模式可知,所有的“工厂”有一个共同点:每个工厂都会提供创建对象的函数。
既然所有工厂都实现了同一类功能,那么我们可以为工厂抽象出一个公共接口(虚基类),此接口定义了创建工厂子类的功能。
这种场景是否似曾相识?是的,工厂和工厂的功能接口构成了使用工厂模式的场景。
即工厂本身也适用于工厂模式。
使用工厂模式来设计工厂,必然要写一个生产工厂的工厂。
生产工厂的工厂,返回值是工厂的抽象接口类,所以这种设计模式叫“抽象工厂模式”。
其实,笔者觉得把这种设计模式叫做“工厂工厂模式”更容易理解。
如果只有一个工厂就不要使用抽象工厂模式了,只有在工厂很多时,才使用抽象工厂模式。
需求不稳定时,不要过度设计,一切都可能被推翻。
对于小的项目,不需要过度追求使用设计模式,架构的代码最好只占整个项目代码的一小部分,否则就是主次颠倒,给自己找麻烦。
对于大的项目,在需求较稳定的情况下,为了提高可维护性、扩展性,可以考虑使用设计模式。
另外,抽象工厂模式有一定的理解难度,要考虑你设计的代码,其他人是否能够读懂,简单易懂也是需要考虑的方面。
所以,从设计模式的本质来看, 先看例子: 单例模式。
上面的例子都是允许一个类被创建多次的。
如果我们想要限制一个类只被创建一次,即只有一个全局可访问的实例(和C语言中的全局变量一样),例如应用程序对象,每个应用程序都应该只有一个应用程序对象。
此时应该怎么编写代码呢? 答案还是封装。
把不想暴露出来的信息藏起来,把必须暴露的信息暴露出来。
单例模式把类的构造函数设置成private私有访问权限,限制外部无法通过new来创建实例。
只能通过特定的接口来获取实例指针。
需要提及的是,封装时需要考虑多线程安全的问题。
当一个类需要有多个实例存在时,不使用单例模式。
从设计模式的本质上看, 具体的例子和写法,可以参考菜鸟教程中的 建造者模式。
建造者模式的典型使用场景是快餐店的套餐搭配模型。
套餐由若干个单个餐品组合而成。
单个餐品又由不同的原材料构成。
这种层层组合的树形对象关系的应用场景下,为了创建顶层的对象,需要先一层层的创建底层的对象,逐步向上,直到构造出根对象。
这种场景下,使用继承可以将同类的对象关联起来,使用组合可以将不同类型的对象组合起来。
组合就是把不同对象放在一块内存中保存,作为一个整体使用。
完全使用继承来解决此类问题是非常不提倡的。
设计模式理论中有一个原则是:“少用继承,多用组合”。
因为继承是一种强耦合,组合是一种松散的耦合。
耦合不利于适应需求变化,是项目中的一颗定时炸弹。
从设计模式的本质上看, 菜鸟教程中没有提及的一种设计模式是组合模式。
具体内容可以参考: 第四节:组合模式和建筑者模式详解。
这里简单说明一下,组合模式和建造者模式比较像,也是遵循树形对象关系结构。
和建造者模式相比,不同之处在于,子对象和父对象具有相同的类型。
所以可以说,组合模式是简单的建造者模式。
具体的使用场合和实例,见原型模式。
原型模式,在实际使用时可能用得不多。
用一句话描述其特点: 这种克隆是一种内存中的复制行为,速度快,能充分利用已有对象的缓存数据,性能高。
克隆出来的对象具有和原对象相同的属性和行为,可以用来帮助原对象处理一些事务。
用一句动漫中的词汇来描述,“影分身”再合适不过了。
从设计模式的本质看, 下一篇,我们将介绍结构型模式。

设计模式的C语言应用-表驱动模式
在C语言编程中,表驱动模式是一种独特的技术,它巧妙地替代了if-else和case语句,通过索引操作直接从数组中获取结果或调用处理函数。
这种模式是非面向对象的,尤其适合于C等底层语言,它强调数据和逻辑的清晰分离,使得代码更易于维护和扩展。
表驱动的核心在于,它根据输入的直接或间接索引来获取信息,这简化了复杂的逻辑判断。
按照输入因素,我们可以将其分为三类:直接访问(如整数月份天数的查找)、索引访问(处理复杂映射关系)和阶梯访问(针对分段范围的处理);根据输入个数,区分一维和多维查找,以适应不同的数据结构需求。
以计算月份天数为例,常规if-else代码被替换为存储在Days_in_Month数组中的数据,提高了效率和代码清晰度。
实际应用实例</
在设备工作流程中,通过表驱动方法处理df_type,根据acq_cnt、zsl、cap_nzsl和small_line_buffer的组合,定义df_type_tab数组。
对于非法值,使用DF_MAX符号表示,而small_line_buffer通过布尔转换简化为0或1,作为索引访问的依据。
在这种模式下,输入因素难以量化或范围过大时,索引模式显得尤为有效。
索引模式避免了大量重复或无效值造成的内存浪费,同时处理无法直接量化的输入。
它实质上是数据密集型存储和访问,通过中介序号简化原始数据处理,提升了代码的可维护性和可读性。
直接模式和索引模式在数据查找层面虽然相似,但阶梯模式则处理连续范围内的数据,如汽车重量分类。
例如,汽车管理通过索引映射重量与操作,简化了代码逻辑。
在姓名、年龄、体重等数据中,索引模式同样起着关键作用。
表驱动在状态机和命令模式等高级编程模式中广泛应用,如华为云社区的实例文章,展示了其在复杂系统中的实际效果。
总结与启示</
表驱动模式有效地降低了if-else和switch的复杂性,通过将逻辑集成到数组中,提高了代码的效率和可维护性。
无论是在基础数据处理还是高级编程实践中,它都是C语言程序员值得掌握的高效工具。
C++ 设计模式 - 策略模式
策略模式定义多种处理同一场景的不同算法,这些算法可在不影响用户的情况下互相替换。
应用场景某会员制商场有两种级别会员:银卡会员、黄金会员,分别享有9折、8折购物优惠。
同时不同的会员用户在生日当天购物,会赠送不同的生日礼物。
分析场景比较简单,需要解决的问题是区分不同类型的顾客享有不同的权益(折扣和生日礼物)。
按照平常的编码习惯,通常会在需要区分用户等级的业务上加上if判断,实现不同等级顾客应享有的不同权益。
这种方案能快速的解决实际问题,但是随着业务需要,商场又要引进更高逼格的会员类型,譬如白金会员、钻石会员等。
此时,需要在散落在各处的业务代码上加上if补丁。
这种做法会引来如下问题:解决方案引入策略模式,将用户等级抽象,分别定义出用户所有的行为,不同等级的用户各自实现该等级应享有的权益。
策略模式CShop: 商场类。
实现不同等级顾客的折扣结算、生日礼物等。
持有CConsumer指针,根据需要指向具体的顾客实例(CCommonUser、CSilverUser、CGoldUser)。
CConsume: 顾客抽象类。
定义顾客所有的行为接口。
CCommonUser、CSilverUser、CGoldUser: 具体顾客类。
不同等级顾客实现有差异部分的接口。
执行效果客户端实现总结源码商店类接口更新顾客类型顾客类抽象接口具体顾客类:黄金会员客户端接口推荐文章C++ 设计模式 - 命令模式开源519文章目录