C++ 设计模式:解决软件的设计问题
导言
在软件开发中,设计模式是一组经过验证的解决方案,用于解决常见的软件设计问题。它们是通过多年实践和经验总结出来的,可以帮助开发者很好地解决复杂的设计难题。本博客将介绍一些常见的C++设计模式,以及它们在实际项目中的应用。
1、设计模式的概述
设计模式主要分为三类:创建型模式、结构型模式和行为型模式。每个模式都有不同的用途和实现方式,适用于不同类型的设计问题。
2、创建型设计模式
创建型设计模式关注对象的创建过程,它们帮助我们封装对象创建的细节,以及更加灵活地创建对象。
2.1 单例模式 (Singleton Pattern)
单例模式确保一个类只有一个实例,并提供全局访问点。它通常用于需要全局唯一实例的场景,如配置对象、线程池等。
优点
单例模式可以保证内存里只有一个实例,减少了内存的开销。
可以避免对资源的多重占用。
单例模式设置全局访问点,可以优化和共享资源的访问。
缺点
单例模式一般没有接口,扩展困难。
单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则
实例
1 | class Singleton { |
2.2 工厂模式 (Factory Pattern)
工厂模式用于封装对象的创建过程,通过工厂方法来创建对象。它隐藏了具体对象的创建细节,客户端只需与工厂接口交互,而不需要了解具体产品的实现细节。
抽象工厂模式:抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类(围绕一个超级工厂创建其他工厂,该超级工厂称为工厂的工厂)
抽象工厂模式得主要角色:
1、抽象工厂(Abstract Factory)提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
2、具体工厂(Concrete Factory)主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
3、抽象产品(Product)定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
4、具体产品(ConcreteProduct)实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系
假设我们有两个产品族:电视和手机,每个产品族中有不同型号的产品(如Samsung TV、Sony TV、iPhone、Samsung Phone等)。抽象工厂定义了创建不同产品族的接口,具体工厂则负责创建具体的产品。
以下是抽象工厂模式的示例代码:
1 |
|
抽象工厂模式可以保证产品族的一致性,同时避免了具体产品类的直接耦合,使得系统更加灵活和易于扩展。
2.3 原型模式 (Prototype Pattern)
原型模式使用原型对象来克隆新的对象,避免重复创建。它通过复制已有对象的状态来创建新对象,而不是通过构造函数创建。
1 | // 抽象原型类 |
3、结构型设计模式
结构型设计模式关注类和对象的组合,帮助我们解决对象之间的关系和依赖问题。
3.1 适配器模式 (Adapter Pattern)
适配器模式用于将一个类的接口转换成客户端所期望的接口。它解决因接口不兼容而不能工作在一起的问题
1 | // 目标接口 |
3.2 代理模式(Proxy Pattern)
它允许通过创建一个代理对象来控制对另一个对象的访问。代理模式通常用于在访问实际对象时添加额外的功能或控制,而无需修改实际对象的代码。
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
代理模式的结构包括三个主要角色:
1、抽象主题(Subject): 定义了真实主题(Real Subject)和代理(Proxy)对象的共同接口,使得代理可以替代真实主题,并与真实主题保持一致。抽象主题可以是一个抽象类或接口。
2、真实主题(Real Subject): 定义了真正执行业务逻辑的类,代理模式的目标是对真实主题进行控制和保护,而不是直接与其交互。
3、代理(Proxy): 实现了抽象主题接口,并持有一个真实主题的引用。代理可以在执行真实主题之前或之后添加额外的功能,例如权限控制、缓存、延迟加载等。
以下是一个简单的代理模式示例:
1 |
|
代理模式的优点在于:
- 可以控制和保护真实主题,实现了客户端和真实主题之间的解耦。
- 可以在不修改真实主题代码的情况下添加额外的功能。
- 可以实现延迟加载,只有在需要时才实例化真实主题对象。
然而,代理模式也有一些缺点,其中一个是可能增加了系统的复杂性,因为每个真实主题都需要一个代理对象。另外,在某些情况下,代理模式可能会降低系统的性能,特别是当代理对象执行一些复杂的操作时。因此,在使用代理模式时,需要根据具体的需求和情况来进行权衡和选择。
4、行为型模式
4.1观察者模式(Observer Pattern)
也称为发布-订阅(Publish-Subscribe)模式。它用于定义对象之间的一种一对多的依赖关系,使得一个对象的状态发生变化时,所有依赖它的对象都会得到通知并自动更新。
在观察者模式中,有以下几个核心角色:
1、主题(Subject): 主题是被观察的对象,它包含了一组观察者对象,并提供用于添加、删除和通知观察者的接口。主题通常具有状态,当状态发生改变时,会通知所有观察者
2、观察者(Observer): 观察者是接收主题通知的对象,它定义了一个更新接口,用于在主题状态改变时得到通知并执行相应的操作。
3、具体主题(Concrete Subject): 具体主题是实际的被观察对象,它继承自主题类。当具体主题的状态发生变化时,会通知所有注册的观察者。
4、具体观察者(Concrete Observer): 具体观察者是实际的观察者对象,它继承自观察者类。当接收到主题的通知时,具体观察者会执行特定的操作。
观察者模式的实现可以采用以下步骤:
1、定义主题接口,并在主题接口中包含注册、注销和通知观察者的方法。
2、定义观察者接口,并在观察者接口中声明更新方法。
3、创建具体主题类,实现主题接口,其中包含一个观察者列表用于保存注册的观察者,并在状态发生改变时通知观察者。
4、创建具体观察者类,实现观察者接口,实现更新方法以执行特定操作。
下面是一个简单的观察者模式示例:
1 |
|
优点:观察者模式可以帮助构建松散耦合的系统,使得主题和观察者可以独立地演化而不互相影响。它广泛应用于事件驱动系统、用户界面组件、消息传递系统等场景。