23种设计模式(C++)

 C++
时间:

设计模式遵循的原则

  1. 开闭原则(Open Close Principle)

对扩展开放,对修改关闭。

  1. 里氏代换原则(Liskov Substitution Principle)

只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

  1. 依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。

  1. 接口隔离原则(Interface Segregation Principle)

使用多个隔离的借口来降低耦合度。

  1. 迪米特法则(最少知道原则)(Demeter Principle)

一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

  1. 合成复用原则(Composite Reuse Principle)

原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改。

应用场景

  • Factory(工厂模式)

使用场景:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

这个模式本身很简单而且使用在业务较简单的情况下。一般用于小项目或者具体产品很少扩展的情况(这样工厂类才不用经常更改)。

日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。

数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。

设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。

案例与说明

  • AbstactFactory(抽象工厂模式)

抽象工厂模式的用意为:

给客户端提供一个接口,可以创建多个产品族中的产品对象。

而且使用抽象工厂模式还要满足一下条件:

1.系统中有多个产品族,而系统一次只可能消费其中一族产品

2.同属于同一个产品族的产品以其使用。

QQ 换皮肤,一整套一起换。

生成不同操作系统的程序。

案例与说明

  • Singleton(单例模式)

使用场景:

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

1.要求生成唯一序列号的环境;

2.在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;

3.创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源;

4.需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式(当然,也可以直接声明为static的方式)。

案例与说明

  • Builder(建造者模式)

使用场景

隔离复杂对象的创建和使用,相同的方法,不同执行顺序,产生不同事件结果

多个部件都可以装配到一个对象中,但产生的运行结果不相同

产品类非常复杂或者产品类因为调用顺序不同而产生不同作用

初始化一个对象时,参数过多,或者很多参数具有默认值

Builder模式不适合创建差异性很大的产品类

产品内部变化复杂,会导致需要定义很多具体建造者类实现变化,增加项目中类的数量,增加系统的理解难度和运行成本

需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;

案例与说明

  • Prototype(原型模式)

使用场景

资源优化场景。

类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。

性能和安全要求的场景。

通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

一个对象多个修改者的场景。

一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。

在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。

案例与说明

  • Bridge(桥接模式)

使用场景

如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。

对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。

一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。

  • Adapter(适配器模式)

使用场景

系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。

想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

  • Decorator(装饰器模式)

使用场景

扩展一个类的功能。

动态增加功能,动态撤销。

  • Composite(组合模式)

部分、整体场景,如树形菜单,文件、文件夹的管理。

  • Flyweight(享元模式)

使用场景

系统有大量相似对象。

需要缓冲池的场景。

  • Facade(外观模式)

使用场景

为复杂的模块或子系统提供外界访问的模块。

子系统相对独立。

预防低水平人员带来的风险。

  • Proxy(代理模式)

使用场景

按职责来划分,通常有以下使用场景:

远程代理。

虚拟代理。

Copy-on-Write 代理。

保护(Protect or Access)代理。

Cache代理。

防火墙(Firewall)代理。

同步化(Synchronization)代理。

智能引用(Smart Reference)代理。

  • Template(模板模式)

使用场景

有多个子类共有的方法,且逻辑相同。

重要的、复杂的方法,可以考虑作为模板方法。

  • Strategy(策略模式)

使用场景

如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

一个系统需要动态地在几种算法中选择一种。

如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

  • State(状态模式)

使用场景

行为随状态改变而改变的场景。

条件、分支语句的代替者。

  • Observer(观察者模式)

使用场景

一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

一个对象必须通知其他对象,而并不知道这些对象是谁。

需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

  • Memento(备忘录模式)

使用场景

需要保存/恢复数据的相关状态场景。

提供一个可回滚的操作。

  • Mediator(中介者模式)

使用场景

系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。

想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

  • Command(命令模式)

使用场景

认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。

  • Visitor(访问者模式)

使用场景

对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作”污染”这些对象的类,也不希望在增加新操作时修改这些类。

  • ChainOfResponsibility(责任链模式)

使用场景

有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

可动态指定一组对象处理请求。

  • Iterator(迭代器模式)

使用场景

访问一个聚合对象的内容而无须暴露它的内部表示。

需要为聚合对象提供多种遍历方式。

为遍历不同的聚合结构提供一个统一的接口。

  • Interpreter(解释器模式)

使用场景

可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。

一些重复出现的问题可以用一种简单的语言来进行表达。

一个简单语法需要解释的场景。


0 评论