C++常用的11种设计模式

工厂模式

定义:将工厂变成一个抽象类,在里面定义一个纯虚函数,具体生成什么产品交给子类继承去决定(抽象产品类-》具体产品类-》抽象工厂类-》具体工厂类)
*
作用:封装对象的创建,解决new解耦的问题
*
适用场景:用来生产同一等级结构中的固定产品。(支持增加任意产品)
*
实例:水果例子;数据库访问;
*
优点:当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,符合开闭原则。
*
缺点:每增加一个产品就要增加一个产品工厂的类,增加了额外的开发量。

单例模式(懒汉式、饿汉式)

定义:一个单例类只创建自己的唯一实例对象,有且只有一个,这个单例类提供了一种访问其唯一实例的对象的方式,可以直接访问,不需要实例化该类的对象。
*
作用:在整个程序空间中,该类只存在一个实例对象。
*
实现步骤:1、构造函数私有化。2、提供一个全局的静态方法(全局访问点)。3、在类中定义一个静态指针,指向本类的静态变量指针。
*
适用场景:创建的一个对象需要消耗的资源过多,比如I/O雨数据库的连接。
*
实例:1、每部苹果手机都有自己的唯一序列号。2、一个班级只有一个班主任。3、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。4、 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
*
优点:1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如页面缓存)。2、避免对资源的多重占用(比如文件的写操作)。
*
缺点:没有接口,不能继承,一个类只关心内部逻辑,而不关心外面怎么样来实例化。

适配器模式

定义:适配器模式是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。例如,读卡器是作为内存卡和笔记本之间的适配器。将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

其中适配器模式又分为类适配器和对象适配器
*
类适配器采用多继承实现,并提供适配后的接口;对象适配器是将需要适配的对象进行包装然后提供给适配后的接口。
*
适用场景:有动机的修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
*
实例:1、美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V。 2、JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,则要将以前系统的 Enumeration 接口转化为 Iterator 接口,这时就需要适配器模式。 3、在 LINUX 上运行 WINDOWS 程序。 4、JAVA 中的 jdbc。
*
优点:1、可以让任何两个没有关联的类一起运行 2、提高了类的复用 3、增加了类的透明度 4、灵活性好
*
缺点:过多的使用适配器,会让系统显得很凌乱,不易整体把握。

外观模式

定义:提供了一个统一的接口,用来访问子系统的一群接口。向现有的系统添加一个接口,用来隐藏系统的复杂性。
作用:简化类的接口,让一系列的复杂过程封装到内部,对外只提供最简单的接口。
适用场景:1、客户端不需要知道系统内部的复杂联系,,整个系统只需要提供一个“接待员”即可。2、定义系统的入口。3、为复杂的模块或子系统提供外界访问的模块。4、子系统相对独立。
实例:1、自己做大餐(很烦很复杂,过程多)VS到餐厅做大餐(接待员一键式安排,自己等着就好)2、去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。
优点:1、减少系统的相互依赖,所有的依赖都是对外观类的依赖,与子系统无关。2、对用户隐藏了子系统的具体实现,减少用户对子系统的耦合,这样就算具体的子系统发生了改变,用户也不会知道。3、提高安全性。
缺点:不符合开闭原则,如何业务变更,则需要修改外观类,继承重写都不合适。

代理模式

定义:为其它对象提供一种代理,以控制对这个对象的访问。用户操作代理,代理操作具体的类。
*
作用:所谓代理模式就是在用户和具体类之间加一个代理类,起到一个中介的作用。
*
适用场景:1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
*
实例:1、Windows里面快捷方式。2、猪八戒去找高翠兰,结果高翠兰是孙悟空变得,这个孙悟空就是高翠兰的代理类,把高翠兰的外貌抽象出来,孙悟空和高翠兰都实现了这个接口,而猪八戒看不出来高翠兰其实是孙悟空变得。3、火车票不一定是在火车站买,也可以在代售点或者各种app上买。 4、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。5、卖书(书店和淘宝作为代理商,用户通过代理商买书)。 6、智能指针。7、Java里面的spring aop。
*
优点:1、代理模式能将代理对象与真实对象被调用的目标对象分离,降低了系统的耦合度,扩展性好,保护目标对象,增强目标对象
*
缺点:1、代理模式会造成系统设计中类的数目增加,增加了系统的复杂度,2、在客户端和目标对象之间增加一个代理对象会造成请求处理速度变慢。
*

包装模式(装饰器模式)

定义:以透明动态的方式来动态扩展对象的功能,也是继承关系的一种代替方案(合成复用原则:组合大于继承)。允许向一个现有的对象添加新的功能,同时又不改变其结构,是作为现有类的一个包装。
*
作用:在不想增加很多子类的情况下扩展。
*
适用场景:1、扩展一个类的功能。2、动态增加功能,动态撤销。
*
实例:1、开奶茶店 (需要加各种配料)2、老婆化妆(各种化妆品) 3、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 4、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。5、汽车功能(走、跑、飞、潜水。。。)
*
优点:1、饰器模式与继承关系的目的都是要扩展对象的功能,但是装饰器模式比继承提供更多的灵活性(动态选择)。2、通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合(二维象限)。
*
缺点:装饰器模式会导致设计中出现很多小类,过度使用会使程序变得很复杂。

桥接模式

定义:将抽象部分与他的实现部分相分离,使他们都可以独立的变化。

作用:一维扩展用继承/组合,多维扩展用桥接。(实现系统可能有多个角度分类,每一种角度都可能变化,那么把这种多角度分类给分离出来让他们独立变化,减少他们之间耦合。)(不是继承,而是关联)
*
抽象部分-》优化的抽象部分-》实现部分-》实现部分的具体实现
*
适用场景:1、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
*
实例:1、电脑系统组装 2、家电各种电器与品牌的关系3、汽车品牌与发电机
*
优点:抽象与实现的分离、优秀的扩展能力、实现细节对用户透明
*
缺点: 1、桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。2、桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。

模板方法模式

定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
*
作用:模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
*
适用场景:1、一次性实现一个算法的不变部分,可变的部分交给子类去实现。2、各子类中的公共行为应被提取出来并集中到一个公共父类中以避免代码重复。3、需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。
*
实例:1、学生都需要去上课,其上课的具体流程是上课、听课、下课,但是不同类学生听课(上课、下课)的具体内容不同。2、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 3、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。
*
优点:1、封装不变部分,扩展可变部分。2、提取公共代码,便于维护。3、行为由父类控制,子类实现。
*
缺点:每一个不同的实现都需要一个子类去实现,导致类的个数增加,使得系统更加庞大。
*
注意事项:一般模板方法都加上final关键字,防止恶意操作。

策略模式

定义:定义了一系列的算法,并将每一个算法封装起来,而且可以使他们可以相互替换。
*
作用:让算法独立于使用他们的客户而独立变化。(在有多种算法相似的情况下,使用if…else所带来的复杂和难以维护)。
*
适用场景:1、如果在一个系统里由很多类,而这些类之间的区别仅是行为不同,那就需要用策略模式来让对象动态的在许多行为中选择一个行为。2、一个系统需要动态的在几种算法中选择一种。3、如果一个对象有很多的行为,如果使用不恰当的模式,这些行为就只好使用多重的条件语句来实现。
*
实例:1、鸭子游戏 2、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。3、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
*
优点:1、算法可以自由切换 2、避免使用多重条件判断 3、扩展性好。
*
缺点:1、策略类会很多 2、所有策略类都需要对外暴露。

观察者模式

定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。(触发联动)
*
作用:一个对象状态改变给其它对象通知的问题,而考虑到易用和低耦合,保证高度的协作。
*
可以将观察者们放进一个容器里。
*
适用场景:1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这些方面封装在独立的对象中使他们可以各自独立的改变和复用。2、一个对象的改变将导致其它一个或者多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。3、一个对象必须通知其他对象,而并不知道这些对象是谁。4、需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
*
实例:1、拍卖的时候,拍卖师观察最高拍价,然后通知给其它拍卖家。2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。
*
优点:1、观察者和被观察者是抽象耦合的。2、建立一套触发机制。
*
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标状态发生了变化。

责任链模式

定义:将所有请求的处理者通过前一对象记住下一个对象的引用而形成一条链,当有请求发生时,可以沿着这条链进行传递,知道有对象处理为止。
*
作用:客户只需要将请求发送到责任链上即可,无需关心请求的处理细节和请求的传递过程,所以责任链将请求的发送者和请求的处理者相耦合了。
*
适用场景:一个请求有多个处理对象(处理者可以动态配置、处理者的顺序可以动态配置、请求不需要指定具体的处理者)
*
实例:1、假如规定学生请假小于或等于 2 天,班主任可以批准;小于或等于 7 天,系主任可以批准;小于或等于 10 天,院长可以批准;其他情况不予批准。2、击鼓传花。
*
优点:1、降低耦合度,它将请求的发送者和请求的处理者解耦。2、简化了对象,使得对象不需要知道链的结构。3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
*
缺点:1、执行未处理:不能保证请求一定会被接收到。2、执行路径长:系统性能将会受到一定影响,而且在进行调试代码时不太方便。3、执行的死循环:建链不当导致环形链表,死循环。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页