美文网首页
c++ 常用设计模式

c++ 常用设计模式

作者: lx_jian | 来源:发表于2019-08-27 09:39 被阅读0次

    参考链接:https://www.cnblogs.com/chengjundu/p/8473564.html

    1.简单工厂模式

    工厂模式有一种非常形象的描述,建立对象的类就如一个工厂,而需要被建立的对象就是一个个产品;在工厂中加工产品,而使用产品的人,不用在乎产品是如何生产出来的。从软件开发的角度来说,这样就有效的降低了模块之间的耦合。主要特点是需要在工厂类中做判断,从而创造相应的产品,当增加新产品时,需要修改工厂类。

    使用情景: 

      在不确定会有多少个处理操作时应该考虑使用简单工厂模式,如针对同样的接收到的数据,处理的逻辑可能会不同,可能以后还会增加新的操作。

    案例: 

    图一

    2.工厂方法模式

    是指定义一个创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到其子类。

     主要解决:主要解决接口选择的问题。针对同样的数据,不同的操作用不同的接口。

    何时使用:我们明确地计划不同条件下创建不同实例时。

     如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。

     关键代码:创建过程在其子类执行。

      缺点:每增加一种产品,就需要增加一个对象工厂。相比简单工厂模式,工厂方法模式需要定义更多的类。

    图二

    3.抽象工厂模式

    提供一个创建一系列相关或相互依赖的对象接口,而无需指定它们的具体类。

     主要解决:主要解决接口选择的问题。

     何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。

     如何解决:在一个产品族里面,定义多个产品。

     关键代码:在一个工厂里聚合多个同类产品。

    缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

    图三

    4.策略模式

    策略模式:是指定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。使得算法可以独立于使用它的客户而变化,也就是说这些算法所完成的功能是一样的,对外接口是一样的,只是各自现实上存在差异。

    主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

    何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

     如何解决:将这些算法封装成一个一个的类,任意地替换。

      关键代码:实现同一个接口。

      缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。

    图四


    5.单例模式

    保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    主要解决:一个全局使用的类频繁地创建与销毁。

     何时使用:想控制实例数目,节省系统资源的时候。

    如何解决:判断系统是否已存在单例,如果有则返回,没有则创建。

    关键代码:构造函数是私有的。

    单例大约有两种实现方法:懒汉与饿汉。

    懒汉:故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化,所以上边的经典方法被归为懒汉实现;

    饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。

    特点与选择:

        由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。

        在访问量较小时,采用懒汉实现。这是以时间换空间。

    图5

    6.访问者模式

    适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中(做任何更改不需要修改基类,不依赖虚函数)

    7.观察者模式

    将复杂对象的构建和其表示分离,使得同样的构建过程可以创建不同的表示。

    主要解决:一个复杂对象的创建工作,由各个部分的子对象用一定的算法构成;由于需求变化,这个复杂对象的各个部分经常面临变化,但将它们组合在一起的算法却相对稳定。

    如何解决:将变与不变分开

     关键代码:建造者:创建和提供实例,Director:管理建造出来的实例的依赖关系。。

     缺点:1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。

    图七

    8.建造者模式

    使得产品内部表象可以独立地变化,客户不必知道产品内部组成的细节。可以强制实行一种分步骤进行的建造过程。用一个接口完成不同的操作,需要对客户的需求进行把握。(如:登陆QQ,自动选择所在地的服务器)

    9.解释器模式

    给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。(如:360读取lua脚本,这个细节的实现就是解释器模式)

    10.命令模式

    把发出命令的责任和执行命令的责任分割开,委派给不同的对象允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。(命令模式在客户端与服务器之间用的最多 (C/S架构))

    11.模板模式

    定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

    主要解决:多个子类有相同的方法,并且逻辑相同,细节有差异。

    如何解决:对重要,复杂的算法,将核心算法设计为模板方法,周边细节由子类实现,重构时,经常使用的方法,将相同的代码抽象到父类,通过钩子函数约束行为。

    关键代码:在抽象类实现通用接口,细节变化在子类实现。

     缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

    图11

    12.桥接模式

    将抽象化与实现化脱离,使得二者可以独立的变化,也就是指在一个软件系统的抽象化和实现化之间使用组合聚合关系而不是继承关系,从而使两者可以独立的变化。(相当于配电脑去装机,把各个模块组合到一起)

    13.适配器模式

    将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。

    主要解决:主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。

     何时使用: 1、系统需要使用现有的类,而此类的接口不符合系统的需要。 2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。 3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)

     如何解决:继承或依赖(推荐)。

     关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。

    缺点:1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。

    图13

    14.外观模式

    外部与一个子系统的通信必须通过一个统一的外观对象进行。每一个子系统只有一个外观类,而且此外观类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个外观类。(多个子系统方法都需要一个外观类统一管理,用统一的接口方便消费者使用)

    15.享元模式

    享元模式大幅度的降低内存中对象的数量,使用享元模式主要是为了优化内存,相同功能可以并行使用。

    16.原型模式

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

    主要解决:在运行期建立和删除对象。

     何时使用:1).当我们的对象类型不是开始就能确定的,而这个类型是在运行期确定的话,那么我们通过这个类型的对象克隆出一个新的对象比较容易一些;2).有的时候,我们需要一个对象在某个状态下的副本,此时,我们使用原型模式是最好的选择;例如:一个对象,经过一段处理之后,其内部的状态发生了变化;这个时候,我们需要一个这个状态的副本,如果直接new一个新的对象的话,但是它的状态是不对的,此时,可以使用原型模式,将原来的对象拷贝一个出来,这个对象就和之前的对象是完全一致的了;3).当我们处理一些比较简单的对象时,并且对象之间的区别很小,可能就几个属性不同而已,那么就可以使用原型模式来完成,省去了创建对象时的麻烦了;4).有的时候,创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程。

     ->适当的时候考虑一下原型模式,能减少对应的工作量,减少程序的复杂度,提高效率

     如何解决:利用已有的一个原型对象,快速地生成和原型对象一样的实例。

      关键代码:拷贝,return new className(*this);

    图16

    17.责任链模式

    在责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。(例如:晚上去上英语课,为了好开溜坐到了最后一排,哇,前面坐了好几个漂亮的MM哎,找张纸条,写上“Hi, 可以做我的女朋友吗?如果不愿意请向前传”,纸条就一个接一个的传上去了,糟糕,传到第一排的MM把纸条传给老师了)

    18.中介者模式

    中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。(如:TCP/IP打洞技术)

    19.装饰模式

    装饰模式以对客户端透明的方式扩展对象的功能是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能

    20.状态模式

    意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。(如:到了晚上12点要睡觉,到了早上8点要起床...这就是状态)

    21.合成模式

    将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。(用于树状结构)

    相关文章

      网友评论

          本文标题:c++ 常用设计模式

          本文链接:https://www.haomeiwen.com/subject/tnpziqtx.html