作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
设计模式是为了解决在软件开发过程中遇到的某些问题而形成的思想。同一场景有多种设计模式可以应用,不同的模式有各自的优缺点,开发者可以基于自身需求选择合适的设计模式,去解决相应的工程难题。
良好的软件设计和架构,可以让代码具备良好的可读性、可维护性、可扩展性、可复用性,让整个系统具备较强的鲁棒性和性能,减少屎山代码出现的概率。
想要熟练运用设计模式,提高自己的编程能力和架构能力,只有在自己工作中,结合自身工作内容,多思考多实践。本文只能通过举一些通俗的例子,来帮助你更快或者说更容易地去理解设计模式的一些底层逻辑,光看可不行哦,一定要多动手实操,看完本文就去实践吧。
该原则:对一个类而言,其职责应该只有一个,即只有一个可以引起其改变的原因。
若类承担的职责过多,其内部耦合性就大大增加,某个职责的变化会带给其他职责不可预估的影响,这样设计会使得类相对脆弱。
通俗地理解就是,你如果在当保安,就不要老想着帮清洁打扫卫生,你的领导可能会因为你打扫卫生夸你,但更可能会因为你保安工作没做到位而骂你。
该原则:面向对象编程领域中规定,软件中的对象应该对于扩展是开放的,对于修改是封闭的,即一个实体允许在不改变它原有源代码前提下变更其行为。
开闭原则可以使我们的软件具备较优的鲁棒性,代码更模块化且利于扩展和维护,从而提高开发效率。经常开发的工程师都清楚,在一个旧的系统中添加新的功能是很不容易的,如果你添加功能要大量修改原有的代码内容,大概可能出现如下几类情况:
综上来看,如果系统有良好的设计,也尽可能满足了开闭原则,那么后续在扩展新功能时,原有系统不会受到影响,只需要针对新扩展的部分重点测试即可(测试工程师狂喜),即便是扩展的功能出现了问题,也相对容易进行修复,最坏就是把扩展的内容全删掉罢了。
该原则:任何基类可以出现的地方,子类一定可以出现。
该原则是继承复用的基石,只有子类能完全替换基类,且功能不受影响,基类才算是真正被复用。想满足该原则,一般来说就尽量从抽象类继承,而不是从具体类继承,还可以根据如下4点来判断:
里氏代换原则可以很大程度降低代码出问题的概率,也是一个良好的设计和编程习惯。
该原则:程序要依赖于抽象接口,不要依赖于具体实现,对抽象编程,不要对实现编程,这样降低了客户端和实现模块间的耦合。一般情况抽象变化的概率小,依赖于抽象,即使实现细节一直变化,也不影响客户端。
想遵循该原则,尽量满足如下4点要求:
依赖倒置原则的目的就是实现解耦,高层模块不再依赖于具体实现。
该原则:也称为迪米特原则,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果需要调用另一个对象的某个方法,可以通过引入一个合理的第三者来调用,从而降低他们之间的耦合度。
想遵循该原则,尽量满足如下3点要求:
最小知识原则尽可能地减少了对象间的联系,保持功能模块相对独立,降低依赖。
该原则:在一个新的对象中使用已有的对象,使之成为新对象的一部分,通过委派调用已有对象的方法达到复用目的,应优先采用合成/聚合的方式,其次采用继承方式。
通过合成/聚合复用的优势:
应用合成复用原则,不要放松对嵌入对象的管理,尤其是嵌入对象过多时,这很考验开发者的实力。
3.1-3.5是创建型模式,3.6-3.12是结构型模式,3.13-3.23是行为型模式。
单例模式是一种创建型的软件设计模式,在工程项目中非常常见。通过单例模式的设计,使得创建的类在当前进程中只有一个实例,并提供一个全局性的访问点,这样可以规避因频繁创建对象而导致的内存飙升情况。
实现单例模式的三个要点:
1)私有化构造函数:这样外界就无法自由地创建类对象,进而阻止了多个实例的产生。
2)类定义中含有该类的唯一静态私有对象:静态变量存放在全局存储区,且是唯一的,供所有对象使用。
3)用公有的静态函数来获取该实例:提供了访问接口。
单例模式一般分为懒汉式和饿汉式。
1)懒汉式:在使用类对象(单例实例)时才会去创建它,不然就懒得去搞。
2)饿汉式:单例实例在类装载时构建,有可能全局都没使用过,但它占用了空间,就像等着发救济粮的饿汉提前排好队等吃的一样。
实现单例模式通常面临两个问题,线程安全和内存泄漏。针对线程安全,可通过双重检测锁的方式来解决;针对内存泄漏,可通过资源管理的方式来解决,如智能指针和静态嵌套类。
具体代码实现详情见:
设计模式之单例模式(C++)_翟天保Steven的博客-程序员宅基地
工厂模式是一种创建型的软件设计模式。定义一个用于创建对象的工厂接口,并让工厂子类决定实例化哪一个产品类,使产品类的实例化延迟到工厂子类中执行。说白了就是用来造东西的,一般是比较简单的东西,我们不需要知道它如何生产的,直接从工厂拿到产品即可。
工厂模式的优点:
工厂模式的缺点:
举例:水果工厂生产,具体代码实现详情见:
设计模式之工厂模式(C++)_翟天保Steven的博客-程序员宅基地
抽象工厂模式是一种创建型的软件设计模式,该模式相当于升级版的工厂模式。
如果说工厂模式对应一个产品系列,那抽象工厂就对应了多个产品系列。比如工厂模式中有鞋子、衣服和裤子可以生产,那抽象工厂模式就会衍生出耐克工厂和阿迪工厂,这两个工厂分别生产各自品牌的鞋子、衣服和裤子,客户只需要选择具体工厂和想要的产品即可。如果想要替换产品系列,也只需要将具体工厂切换为别的品牌就行了。
抽象工厂模式的优点:
抽象工厂模式的缺点:
举例:不同国家水果工厂生产,具体代码实现详情见:
设计模式之抽象工厂模式(C++)_翟天保Steven的博客-程序员宅基地
建造者模式是一种创建型的软件设计模式,用于构造相对复杂的对象。
建造者模式可以将复杂对象的构建与它的表示分离,使得相同的构建过程可以得到不同的表示。如果说工厂模式和抽象工厂模式更注重产品整体,那建造者模式则更在乎产品的组成和细节。
建造者模式的优点:
建造者模式的缺点:
举例:生产电脑,具体代码实现详情见:
设计模式之建造者模式(C++)_翟天保Steven的博客-程序员宅基地
原型模式是一种创建型的软件设计模式,通俗的来讲就是复制粘贴。
通过一个原型对象,快速地创建出多个一致的对象,并对其进行相关的操作。比如文件夹中存放了一个Word文件,你把文件复制了一个副本出来,原件不动,对副本进行修改以达到自己的目的。原型像是一个模板,你可以基于它复制好多对象,而复制出来的副本产生任何变化都不会影响到原型(注意:前提是clone的实现要满足深拷贝)。
原型模式的优点:
原型模式的缺点:
举例:文件复制粘贴,具体代码实现详情见:
设计模式之原型模式(C++)_翟天保Steven的博客-程序员宅基地
适配器模式是一种结构型的软件设计模式,也称包装模式,即将相对复杂的功能(可能用到多个类)封装起来,提供一个使用者想要的接口,使用者只需要调用接口,不需要知道接口里封装的内容是如何实现的。
个人工作中经常能用到适配器模式,比如在面对一些第三方库或者SDK开发时,它们的接口往往与我们自己想要的接口不一致,此时适配器模式可以很好地扮演一个接口转换器的角色,将别人的接口与我们的接口对应上。
适配器模式的优点:
适配器模式的缺点:
举例:调用第三方相机SDK,具体代码实现详情见:
设计模式之适配器模式(C++)_翟天保Steven的博客-程序员宅基地
类适配器模式:
对象适配器模式:
桥接模式是一种结构型的软件设计模式,将抽象部分与实现部分分离,使他们可以独立地变化。
举例来说,黑色钢笔、红色油笔、红色钢笔等等,如果颜色和笔类型合起来考虑,那类的复杂度将难以想象,若有10个颜色,10个笔类型,那要有10*10个类来涵盖所有类型的笔。但是如果拆分颜色和笔类型,通过组合的形式获得目标,那只要10+10个类即可。这样设计极大降低了系统复杂度和耦合程度。
桥接模式的优点:
桥接模式的缺点:
举例:画笔绘画,具体代码实现详情见:
设计模式之桥接模式(C++)_翟天保Steven的博客-程序员宅基地
组合模式是一种结构型的软件设计模式,将对象组合成树形结构,以凸显“部分-整体”的层次结构,使客户端对单个对象和组合对象的操作具备一致性。
组合模式和桥接模式都应用了组合的思想,不同之处在于:桥接模式侧重于同级别间的组合,如多个属性的组合,避免了类爆炸;组合模式侧重于部分和整体的组合,避免了单对象和组合对象的区别对待,那样会增加程序复杂度。
组合模式的优点:
组合模式的缺点:
举例:文件系统,具体代码实现详情见:
设计模式之组合模式(C++)_翟天保Steven的博客-程序员宅基地
透明式组合模式:
安全式组合模式:
装饰器模式是一种结构型的软件设计模式,在不改变原类文件或使用继承的前提下,动态地扩展一个对象,进而达到增强或者增加对象功能的目的。
装饰器模式的优点:
装饰器模式的缺点:
举例:炒菜加料,具体代码实现详情见:
设计模式之装饰器模式(C++)_翟天保Steven的博客-程序员宅基地
门面模式是一种结构型的软件设计模式,也叫外观模式,它提供了统一的接口去访问多个子系统的接口。举个例子,一个餐馆里有许多角色,每个角色就是一个子系统,餐馆就是总系统,客人来餐馆只需要按要求点餐,不需要管餐馆是怎么运作的。
门面模式的优点:
门面模式的缺点:
举例:餐馆吃饭,具体代码实现详情见:
设计模式之门面模式(C++)_翟天保Steven的博客-程序员宅基地
代理模式是一种结构型的软件设计模式,在不改变原代码前提下,提供一个代理,以控制对原对象的访问。
代理模式的优点:
代理模式的缺点:
举例:游戏代理,具体代码实现详情见:
设计模式之代理模式(C++)_翟天保Steven的博客-程序员宅基地
享元模式是一种结构型的软件设计模式,通过共享对象的方式,尽可能减少内存占用,从而达到优化的目的。
就像打麻将,同时有10桌在玩,每桌都有4个"八筒",如果建立40个"八筒"对象,那就非常冗余,但如果用享元模式建立一套麻将牌,每桌打出"八筒"时,就调用享元中的"八筒",相当于只用了1个对象,这样即节省了资源,也完成了需求。
上述例子中,桌号和牌号就是享元模式的外蕴状态,如A1八筒,就是A桌的第一个"八筒",A和1是外蕴状态;而卡牌"八筒"本身就是内蕴状态,内蕴是可以共享的。外蕴随环境变化,占用资源也少的多,往往只是简单的数据结构。
享元模式的优点:
享元模式的缺点:
举例:模拟打牌,具体代码实现详情见:
设计模式之享元模式(C++)_翟天保Steven的博客-程序员宅基地
策略模式是一种行为型的软件设计模式,针对某个行为,在不同的应用场景下,有不同的实现算法,并且可以互相替换。比如两军交战,军队会采用不同的阵法、策略、兵法应对不同的战况。
策略模式的优点:
策略模式的缺点:
举例:军队策略,具体代码实现详情见:
设计模式之策略模式(C++)_翟天保Steven的博客-程序员宅基地
模板模式是一种行为型的软件设计模式,在父类中定义了一个模板算法,只实现模板中的公共部分,将可变部分放在子类中实现,不同的子类对同一模板有不同的扩展和实现。
模板模式的优点:
模板模式的缺点:
举例:安装电脑,具体代码实现详情见:
设计模式之模板模式(C++)_翟天保Steven的博客-程序员宅基地
命令模式是一种行为型的软件设计模式,行为请求者通过发起命令,使得行为实现者执行命令要求的行为。通常行为请求者和行为实现者之间是强耦合的,而命令模式能很好地将其解耦。
命令模式的优点:
命令模式的缺点:
举例:军队指挥,具体代码实现详情见:
设计模式之命令模式(C++)_翟天保Steven的博客-程序员宅基地
迭代器模式是一种行为型的软件设计模式,提供一种方法能顺序访问聚合对象中的各个元素,而又不暴露其内部。
我们使用的聚合对象各种各样,比如vector、list、tree、map等等,既然是聚合,那就有访问其个体的需要。而遍历访问这个行为可能有深度优先、广度优先、顺序遍历、逆序遍历等等,迭代器的意义就是将这个行为抽离封装起来,这样客户端只需要调用合适的迭代器,来进行对应的遍历,而不用自己去实现这一行为。
迭代器模式的优点:
迭代器模式的缺点:
举例:容器遍历,具体代码实现详情见:
设计模式之迭代器模式(C++)_翟天保Steven的博客-程序员宅基地
中介者模式是一种行为型的软件设计模式,也称为仲裁者模式,顾名思义,该模式的作用就是中介,帮助其他类进行良好的交流。
类之间关系混乱的时候,会有很强的耦合性。就拿租房为例,如果有10个租客,5个房东,他们各自单线联系,那么他们之间的交流会相对混乱,维护起来也复杂的多。此时出现了一个房产中介,它将租客和房东的信息整合起来,由中介安排合适的租客和房东交流,那么交流就变得高效且清晰,当然也要付费的(就像增加中介类的代码维护开销一样)。
中介者模式的优点:
中介者模式的缺点:
举例:房屋租赁,具体代码实现详情见:
设计模式之中介者模式(C++)_翟天保Steven的博客-程序员宅基地
观察者模式是一种行为型的软件设计模式,定义对象间的一种一对多的依赖关系,当被观察者状态发生改变时,所有观察者都做出相应改变。Qt中的信号与槽就是一种典型的观察者模式。
观察者模式的优点:
观察者模式的缺点:
举例:开车等红绿灯,具体代码实现详情见:
设计模式之观察者模式(C++)_翟天保Steven的博客-程序员宅基地
备忘录模式是一种行为型的软件设计模式,在不破坏封装的前提下,获取一个对象的内部状态,并在对象外保存该状态,当对象需要恢复到该状态时,对其进行恢复。
备忘录模式的优点:
备忘录模式的缺点:
举例:存读游戏进度,具体代码实现详情见:
设计模式之备忘录模式(C++)_翟天保Steven的博客-程序员宅基地
状态模式是一种行为型的软件设计模式,当一个对象的内在状态改变时,其行为也随之改变。就像玩游戏的时候,不同的buff状态,角色会有不同的伤害、技能等等。
当控制一个对象状态的条件表达式过于复杂时,很适合用该模式,将复杂的判断逻辑转移到表示不同状态的系列类中,能将逻辑大大简化。
状态模式的优点:
状态模式的缺点:
举例:开关灯,具体代码实现详情见:
设计模式之状态模式(C++)_翟天保Steven的博客-程序员宅基地
责任链模式是一种行为型的软件设计模式,对象内存在对下家的引用,层层连接形成了一条责任链,请求的信息在链上传递直到某个对象决定处理该信息。
责任链模式的优点:
责任链模式的缺点:
举例:申请批假,具体代码实现详情见:
设计模式之责任链模式(C++)_翟天保Steven的博客-程序员宅基地
访问者模式是一种行为型的软件设计模式,表示一个作用于某对象结构中的各元素的操作。使得在不改变各元素类的前提下,能定义作用于这些元素的操作。
该模式适合数据结构相对稳定且算法又易变化的系统。数据结构是被访问者,算法操作相当于访问者。
访问者模式的优点:
访问者模式的缺点:
举例:市长视察学校和企业,具体代码实现详情见:
设计模式之访问者模式(C++)_翟天保Steven的博客-程序员宅基地
解释器模式是一种行为型的软件设计模式,定义了一个解释器,来解释给定语言和文法的句子。也可以理解为翻译吧,比如1+1,翻译为一加上一,等于二,这样就做成了一个简单的加法计算器。
解释器模式的优点:
解释器模式的缺点:
举例:实现简单的加减法计算器,具体代码实现详情见:
设计模式之解释器模式(C++)_翟天保Steven的博客-程序员宅基地
上述讲了这么多关于设计模式的内容,希望我举的例子能帮助你相对容易地理解设计模式。每个模式的链接点进去,都是专门的一篇文章,且附带了完整详细简单的源码,相信多少会给你带来一些帮助!
如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!
文章浏览阅读290次,点赞8次,收藏10次。1.背景介绍稀疏编码是一种用于处理稀疏数据的编码技术,其主要应用于信息传输、存储和处理等领域。稀疏数据是指数据中大部分元素为零或近似于零的数据,例如文本、图像、音频、视频等。稀疏编码的核心思想是将稀疏数据表示为非零元素和它们对应的位置信息,从而减少存储空间和计算复杂度。稀疏编码的研究起源于1990年代,随着大数据时代的到来,稀疏编码技术的应用范围和影响力不断扩大。目前,稀疏编码已经成为计算...
文章浏览阅读217次。EasyGBS - GB28181 国标方案安装使用文档下载安装包下载,正式使用需商业授权, 功能一致在线演示在线API架构图EasySIPCMSSIP 中心信令服务, 单节点, 自带一个 Redis Server, 随 EasySIPCMS 自启动, 不需要手动运行EasySIPSMSSIP 流媒体服务, 根..._easygbs-windows-2.6.0-23042316使用文档
文章浏览阅读1.2k次,点赞27次,收藏7次。2023巅峰极客 BabyURL之前AliyunCTF Bypassit I这题考查了这样一条链子:其实就是Jackson的原生反序列化利用今天复现的这题也是大同小异,一起来整一下。_原生jackson 反序列化链子
文章浏览阅读734次,点赞9次,收藏7次。微服务架构简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是一个可以独立运行的项目。这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除])这么多小服务,他们之间如何通讯?这么多小服务,客户端怎么访问他们?(网关)这么多小服务,一旦出现问题了,应该如何自处理?(容错)这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。_spring cloud
文章浏览阅读5.9k次,点赞6次,收藏20次。Js实现图片点击切换与轮播图片点击切换<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/ja..._点击图片进行轮播图切换
文章浏览阅读10w+次,点赞245次,收藏1.5k次。在开始安装前,如果你的电脑装过tensorflow,请先把他们卸载干净,包括依赖的包(tensorflow-estimator、tensorboard、tensorflow、keras-applications、keras-preprocessing),不然后续安装了tensorflow-gpu可能会出现找不到cuda的问题。cuda、cudnn。..._tensorflow gpu版本安装
文章浏览阅读243次。0x00 简介权限滥用漏洞一般归类于逻辑问题,是指服务端功能开放过多或权限限制不严格,导致攻击者可以通过直接或间接调用的方式达到攻击效果。随着物联网时代的到来,这种漏洞已经屡见不鲜,各种漏洞组合利用也是千奇百怪、五花八门,这里总结漏洞是为了更好地应对和预防,如有不妥之处还请业内人士多多指教。0x01 背景2014年4月,在比特币飞涨的时代某网站曾经..._使用物联网漏洞的使用者
文章浏览阅读786次。A. Epipolar geometry and triangulationThe epipolar geometry mainly adopts the feature point method, such as SIFT, SURF and ORB, etc. to obtain the feature points corresponding to two frames of images. As shown in Figure 1, let the first image be and th_normalized plane coordinates
文章浏览阅读708次,点赞2次,收藏3次。开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先关系再实体)一.第二代开放信息抽取系统背景 第一代开放信息抽取系统(Open Information Extraction, OIE, learning-based, 自学习, 先抽取实体)通常抽取大量冗余信息,为了消除这些冗余信息,诞生了第二代开放信息抽取系统。二.第二代开放信息抽取系统历史第二代开放信息抽取系统着眼于解决第一代系统的三大问题: 大量非信息性提取(即省略关键信息的提取)、_语义角色增强的关系抽取
文章浏览阅读1.1w次,点赞6次,收藏51次。快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力为了寻找一个优质的网页模板,网页设计师和开发者往往可能会花上大半天的时间。不过幸运的是,现在的网页设计师和开发人员已经开始共享HTML5,Bootstrap和CSS3中的免费网页模板资源。鉴于网站模板的灵活性和强大的功能,现在广大设计师和开发者对html5网站的实际需求日益增长。为了造福大众,Mockplus的小伙伴整理了2018年最..._html欢迎页面
文章浏览阅读282次。原标题:2018全国计算机等级考试调整,一、二级都增加了考试科目全国计算机等级考试将于9月15-17日举行。在备考的最后冲刺阶段,小编为大家整理了今年新公布的全国计算机等级考试调整方案,希望对备考的小伙伴有所帮助,快随小编往下看吧!从2018年3月开始,全国计算机等级考试实施2018版考试大纲,并按新体系开考各个考试级别。具体调整内容如下:一、考试级别及科目1.一级新增“网络安全素质教育”科目(代..._计算机二级增报科目什么意思
文章浏览阅读240次。conan简单使用。_apt install conan