设计模式之工厂方法、抽象工厂、生成器、原型、单例

本文深入探讨四种创建型设计模式:工厂方法、抽象工厂、生成器和原型模式。阐述它们的意图、优缺点及适用场景,如避免紧密耦合、支持扩展和维护,以及解决复杂对象创建。此外,还提及单例模式,解释其作用、实现方式和潜在问题,强调资源管理和全局唯一性。
摘要由CSDN通过智能技术生成

工厂方法模式

意图

工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。

优点

  • 你可以避免创建者和具体产品之间的紧密耦合。

  • 单一职责原则*。 你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。

  • 开闭原则*。 无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。

缺点

  • 应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。 最好的情况是将该模式引入创建者类的现有层次结构中。

工厂方法模式适合应用场景

  • 当你在编写代码的过程中, 如果无法预知对象确切类别及其依赖关系时, 可使用工厂方法。
  • 如果你希望用户能扩展你软件库或框架的内部组件, 可使用工厂方法。
  • 如果你希望复用现有对象来节省系统资源, 而不是每次都重新创建对象, 可使用工厂方法。
  • 代码中存在 if-else 分支判断,动态地根据不同的类型创建不同的对象。针对这种情况,我们就考虑使用工厂模式,将这一大坨 if-else 创建对象的代码抽离出来,放到工厂类中。
  • 单个对象本身的创建过程比较复杂,比如前面提到的要组合其他类对象,做各种初始化操作。在这种情况下,我们也可以考虑使用工厂模式,将对象的创建过程封装到工厂类中。

工厂模式和依赖注入容器

DI 容器底层最基本的设计思路就是基于工厂模式的。DI 容器相当于一个大的工厂类,负责在程序启动的时候,根据配置(要创建哪些类对象,每个类对象的创建需要依赖哪些其他类对象)事先创建好对象。当应用程序需要使用某个类对象的时候,直接从容器中获取即可。正是因为它持有一堆对象,所以这个框架才被称为“容器”。


抽象工厂模式

意图

抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。

优点

  • 你可以确保同一工厂生成的产品相互匹配。

  • 你可以避免客户端和具体产品代码的耦合。

  • 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。

  • 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码。

缺点

  • 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。

抽象工厂模式适合应用场景

  • 如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。

  • 在许多设计工作的初期都会使用工厂方法模式(较为简单, 而且可以更方便地通过子类进行定制), 随后演化为使用抽象工厂模式,原型模式或生成器模式(更灵活但更加复杂)。


生成器模式

意图

生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。

用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。

优点

  • 你可以分步创建对象, 暂缓创建步骤或递归运行创建步骤。

  • 生成不同形式的产品时, 你可以复用相同的制造代码。

  • 单一职责原则。 你可以将复杂构造代码从产品的业务逻辑中分离出来。

缺点

  • 由于该模式需要新增多个类, 因此代码整体复杂程度会有所增加。

生成器模式适合应用场景

  • 使用生成器模式可避免 “重叠构造函数 (telescopic constructor)” 的出现。

  • 当你希望使用代码创建不同形式的产品 (例如石头或木头房屋) 时, 可使用生成器模式。

  • 使用生成器构造组合树或其他复杂对象。

  • 构造参数多、参数相互依赖,参数合法检验。


原型模式

意图

原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。

优点

  • 你可以克隆对象, 而无需与它们所属的具体类相耦合。

  • 你可以克隆预生成原型, 避免反复运行初始化代码。

  • 你可以更方便地生成复杂对象。

  • 你可以用继承以外的方式来处理复杂对象的不同配置。

缺点

  • 克隆包含循环引用的复杂对象可能会非常麻烦。

原型模式适合应用场景

  • 如果你需要复制一些对象, 同时又希望代码独立于这些对象所属的具体类, 可以使用原型模式。

  • 如果子类的区别仅在于其对象的初始化方式, 那么你可以使用该模式来减少子类的数量。 别人创建这些子类的目的可能是为了创建特定类型的对象。


单例模式

意图

单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。

优点

  • 你可以保证一个类只有一个实例。

  • 你获得了一个指向该实例的全局访问节点。

  • 仅在首次请求单例对象时对其进行初始化

    缺点

  • 单例对 OOP 特性的支持不友好, 违反了_单一职责原则_。单例对代码的扩展性不友好。

  • 单例会隐藏类之间的依赖关系,单例模式可能掩盖不良设计。

  • 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。

  • 单例对代码的测试不友好。

    为什么要使用单例?

  • 处理资源访问冲突

  • 表示全局唯一类

    如何实现一个单例?

  • 饿汉式

  • 懒汉式

  • 双重检测

  • 静态内部类

  • 枚举

如何理解单例模式中的唯一性?

对于 Java 语言来说,单例类对象的唯一性的作用范围并非进程,而是类加载器(Class Loader),

如何实现线程唯一的单例?

一个线程创建一个单例对象

如何实现集群环境下的单例?

需要把这个单例对象序列化并存储到外部共享存储区(比如文件)。进程在使用这个单例对象的时候,需要先从外部共享存储区中将它读取到内存,并反序列化成对象,然后再使用,使用完成之后还需要再存储回外部共享存储区。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值