创建型设计模式的比较与决策

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 本文深入探讨六种创建型设计模式:单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式。通过概述各模式的核心概念、应用场景和关键要素,帮助读者理解并掌握这些模式的核心思想。文章还通过比较表和决策流程图,直观地展示了各模式之间的差异和选择依据,为读者提供了实用的设计模式选择指南。本文的特色在于结合了理论与实践,每个模式都配有详细的代码示例和结构图,帮助读者更好地理解和应用这些模式。总之,本文旨在为读者提供一篇全面、深入且实用的创建型设计模式指南,帮助读者在实际工作中灵活运用这些模式...


一、设计模式概览

   在软件工程中,设计模式是一套经过精心挑选的通用、可重复使用的解决特定设计问题的模板。它们是在多年软件开发实践中总结出来的最佳实践的集合,用于解决面向对象设计中常见的问题。设计模式可以加速软件开发过程,提高开发效率并促进团队之间的沟通。

   设计模式分类通常分为三大类:

 1. 创建型模式 (Creational Patterns)
 2. 结构型模式 (Structural Patterns)
 3. 行为型模式 (Behavioral Patterns)

1.1 创建型模式

   创建型设计模式关注对象创建的机制,尤其是当一个系统需要独立于其构成的类的实例化方式时。创建型模式的核心思想是将对象的创建和使用分离,以提供更大的系统灵活性。这类模式通常在涉及以下场景时会特别有用:

 1. 当系统需要独立于它的产品的创建、组合和表示时。
 2. 当需要封装一个类的实例化过程时。
 3. 当提供对象创建的多个变体,但不想暴露创建逻辑的细节时。

   创建型模式不仅可以隐藏这些实例化细节,还能通过定义创建接口将、系统中的对象创建与系统的其他部分解耦。这为改变系统内或系统间的对象创建过程提供了灵活性,可以改进代码的模块性、可扩展性和维护性。

       

   常见的创建型模式包括单例模式(Singleton)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)和原型模式(Prototype)。每种模式解决了特定的问题,但它们的共同之处在于使得系统不必关心对象具体如何被创建、组成和表示。

       

   在如今快速变化的软件设计领域,理解和运用创建型模式越来越成为了软件架构师和开发人员的基础技能。通过使用这些模式,开发人员可以更加集中精力在业务逻辑上,而不必过分关注对象创建的复杂性,从而加快开发进度并降低后期的维护成本。

       

   在下一部分中,我们将深入探讨各种创建型模式,了解它们是如何工作的,以及它们在实际应用中如何能够为我们带来架构上的好处。

       

二、比较创建型设计模式

1.1 适用场景典型用例

 1. 单例模式:http://t.csdnimg.cn/gRd4l

  • 当一个类只需要一个实例,并且需要一个全局访问点时,单例模式就非常有用。例如,数据库连接池或日志记录工具通常就是单例。
  • 当系统中只需要一个实例对象,或者需要一个全局访问点来访问某个资源时,可以使用单例模式。例如,配置信息的读取、线程池、缓存管理等。

 2. 简单工厂:http://t.csdnimg.cn/7mLkH

  • 当需要创建的对象不多,且整个系统的设计不复杂时候。简单工厂能够根据传入参数返回多个可能类中的一个实例。
  • 适用于根据传入的参数创建不同类型对象,但不需要知道具体创建细节的场景。例如,根据配置信息创建不同类型的数据库连接对象。

 3. 工厂方法:http://t.csdnimg.cn/ldsMK

  • 与简单工厂相比,当对象的创建逻辑较复杂或对象的类型较多时,每个具体产品的创建都有自己的逻辑时适用工厂方法模式。例如,不同类型的数据库连接工厂或不同风格的UI组件工厂。
  • 适用于系统中有多个具体产品类,并且它们的创建逻辑可能有所不同,但客户端只需要关心接口的场景。例如,不同类型的图形绘制对象创建。

 4. 抽象工厂:http://t.csdnimg.cn/X7iwq

  • 适用于有多种产品族,而系统只消费其中某一系列产品的场景。比如跨平台UI工具箱,需要根据不同操作系统生成不同UI控件。
  • 当需要创建一系列相互关联或依赖的对象时,并且这些对象家族中的对象具有相同的约束条件时,可以使用抽象工厂模式。例如,创建不同主题的皮肤或界面。

 5. 建造者模式:http://t.csdnimg.cn/zUj9V

  • 当需要创建的对象非常复杂,有多个组成部分且这些部分的构建顺序可能不同,也可能需要不同的构建过程时,建造者模式是合适的。例如创建一个复杂的文档或UI布局。
  • 当需要构建的对象具有复杂的内部结构,并且这些对象的构建过程与表示过程相互分离时,可以使用建造者模式。例如,构建具有多个可选配置的复杂对象,如电脑配置、房屋装修等。

 6. 原型模式:http://t.csdnimg.cn/mORjg

  • 适用于创建新对象成本较高时,通过复制现有对象并修改为所需状态更为有效时。如当需要复制或克隆复杂的配置对象。
  • 当需要频繁创建相似对象,并且创建对象的成本较高时,可以使用原型模式。例如,创建大量相似的图形对象、文档对象等。

1.2 关键要素与差异对比

模式 关键要素 差异
单例模式 只有一个实例 保证全局只有一个实例,提供全局访问点
简单工厂模式 创建对象 根据参数创建对象,但客户端需要知道具体类名
工厂方法模式 抽象创建 将创建逻辑抽象到子类中,客户端只需要关心接口
抽象工厂模式 创建对象家族 创建一系列相关或依赖对象,强调对象家族的约束条件
建造者模式 复杂对象构建 将构建过程与表示过程分离,支持多步骤构建
原型模式 克隆对象 通过复制现有对象来创建新对象,节省创建成本
模式名称 实例唯一 参数化实例化 复杂对象构建 对象族 产品类层次 多个构建步骤 克隆
单例 单一类别
简单工厂 扁平结构
工厂方法 分层结构
抽象工厂 分层结构
建造者 单一类别
原型 单一类别
  • 实例唯一:模式是否确保一个类只有一个实例。
  • 参数化实例化:创建实例时是否允许传递参数,从而产生不同种类的对象。
  • 复杂对象构建:是否支持将复杂对象的创建分解成不同部分和步骤。
  • 对象族:是否支持一组相关的产品对象的系列。
  • 产品类层次:是否组织产品类的方式,扁平结构通常指每个类都是独立的,而分层结构则意着存在继承关系。
  • 多个构建步骤:创建对象是否包含一系列步骤。
  • 克隆:创建实例是否通过复制一个原型。

1.3 结构图

image.png

image.gif image.png

image.png        

三、模式选择指南

   在实际的软件设计过程中,选择合适的创建型模式对于提高代码的可维护性、扩展性和灵活性至关重要。然而,面对多种创建型模式,如何选择最适合当前场景的模式可能会成为一项挑战。本部分将提供场景分析和决策流程图,以帮助读者在实际工作中做出恰当的选择。

3.1 场景分析

   在选择创建型模式时,首先要分析当前场景的特点和需求。以下是一些常见的场景及其对应的创建型模式:

 1. 当需要一个全局唯一的实例时:

  • 例如,配置管理、日志记录等场景,适合使用单例模式。这样可以确保整个系统中只有一个实例,避免重复创建和资源浪费。

 2. 当需要根据不同条件创建不同类型对象时:

  • 例如,根据用户输入或配置文件创建不同类型的数据库连接对象,适合使用简单工厂模式。简单工厂模式可以根据传入的参数创建并返回相应类型的对象。

 3. 当需要让子类决定创建何种对象时:

  • 例如,在设计图形绘制系统时,有多种不同类型的图形对象需要创建,适合使用工厂方法模式。工厂方法模式将对象的创建逻辑抽象到子类中,客户端只需要关心接口即可。

 4. 当需要创建一系列相互关联或依赖的对象时:

  • 例如,在设计主题皮肤或界面时,需要同时创建多个相互关联的对象,适合使用抽象工厂模式。抽象工厂模式可以创建并返回一系列相关或依赖的对象,而无需指定具体的类。

 5. 当需要构建复杂对象且构建过程与表示过程相互分离时:

  • 例如,在构建具有多个可选配置的复杂对象时,适合使用建造者模式。建造者模式可以将复杂对象的构建过程拆分为多个步骤,使得构建过程更加清晰和灵活。

 6. 当需要频繁创建相似对象且创建成本较高时:

  • 例如,在创建大量相似的图形对象或文档对象时,适合使用原型模式。原型模式可以通过复制现有对象来创建新对象,从而节省创建成本和时间。

3.2 决策流程图

image.gif

   根据决策流程图,读者可以按照以下步骤进行选择:

  1. 确定是否需要全局唯一的实例:如果是,则选择单例模式;否则,继续下一步。
  2. 确定是否需要根据不同条件创建不同类型对象:如果是,则选择简单工厂模式;否则,继续下一步。
  3. 确定是否需要让子类决定创建何种对象:如果是,则选择工厂方法模式;否则,继续下一步。
  4. 确定是否需要创建一系列相互关联或依赖的对象:如果是,则选择抽象工厂模式;否则,继续下一步。
  5. 确定是否需要构建复杂对象且构建过程与表示过程相互分离:如果是,则选择建造者模式;否则,继续下一步。
  6. 确定是否需要频繁创建相似对象且创建成本较高:如果是,则选择原型模式;否则,可能需要考虑其他非创建型的设计模式或自定义解决方案。

   通过以上场景分析和决策流程图,信息读者可以更加清晰地了解各种创建型模式的适用场景和选择依据,从而在实际工作中做出恰当的选择。

       

四、结语

   创建型设计模式在软件设计中扮演了至关重要的角色,它们为开发者提供了多样化的工具和方法,以灵活且优雅地创建对象。每种创建型设计模式都有其独特的优势和适用场景,正确使用它们可以提高代码的可维护性、扩展性和可重用性。

4.1 优势

 1. 封装性:

  • 创建型设计模式通常能够封装对象的创建逻辑,使得客户端代码与具体实现解耦,提高了代码的模块化和可维护性。

 2. 灵活性:

  • 这些模式允许我们在运行时根据需要创建对象,而不需要在编译时确定所有细节,这提供了很大的灵活性。

 3. 代码重用:

  • 通过复用创建逻辑,可以避免代码重复,提高代码的重用性。

 4. 扩展性:

  • 创建型设计模式能够支持软件的扩展和演化,因为它们允许在不修改现有代码的情况下添加新的对象类型。

4.2 考量因素

 1. 适用场景:

  • 选择创建型设计模式时,需要仔细分析应用场景,确保所选模式能够最有效地解决问题。

 2. 性能开销:

  • 虽然创建型设计模式可以提高代码的灵活性和可维护性,但在某些情况下,它们可能会引入额外的性能开销。因此,在选择模式时需要权衡其带来的好处和可能的性能影响。

 3. 设计复杂度:

  • 使用创建型设计模式可能会增加设计的复杂度,因此,在简单场景中过度使用可能会导致代码难以理解和维护。

 4. 学习成本:

  • 对于初学者来说,掌握并正确应用创建型设计模式可能需要一定的学习和实践成本。

   总的来说,创建型设计模式是软件设计中的重要工具,它们能够帮助开发者构建更加健壮、灵活和可维护的软件系统。然而,在实际应用中,我们需要根据具体场景和需求来选择合适的模式,并权衡其带来的好处和可能的成本。通过不断学习和实践,我们可以更好地掌握这些模式,并将它们应用于实际项目中,以提高软件的质量和效率。

相关文章
|
5天前
|
设计模式 搜索推荐 数据库连接
第二篇 创建型设计模式 - 灵活、解耦的创建机制
第二篇 创建型设计模式 - 灵活、解耦的创建机制
|
6天前
|
设计模式 JavaScript 前端开发
[设计模式Java实现附plantuml源码~创建型] 复杂对象的组装与创建——建造者模式
[设计模式Java实现附plantuml源码~创建型] 复杂对象的组装与创建——建造者模式
|
6天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 对象的克隆~原型模式
[设计模式Java实现附plantuml源码~创建型] 对象的克隆~原型模式
|
6天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 产品族的创建——抽象工厂模式
[设计模式Java实现附plantuml源码~创建型] 产品族的创建——抽象工厂模式
|
6天前
|
设计模式 存储 JavaScript
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
|
6天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
|
6天前
|
设计模式 安全 Java
[设计模式Java实现附plantuml源码~创建型] 确保对象的唯一性~单例模式
[设计模式Java实现附plantuml源码~创建型] 确保对象的唯一性~单例模式
|
6天前
|
设计模式 测试技术 Go
[设计模式 Go实现] 创建型~ 原型模式
[设计模式 Go实现] 创建型~ 原型模式
|
6天前
|
设计模式 测试技术 Go
[设计模式 Go实现] 创建型~工厂方法模式
[设计模式 Go实现] 创建型~工厂方法模式
|
6天前
|
设计模式 测试技术 Go
[设计模式 Go实现] 创建型~建造者模式
[设计模式 Go实现] 创建型~建造者模式