浅谈设计模式

        设计模式(Design Patterns)是指在软件设计中,针对特定问题的最佳实践解决方案。它们是经过反复验证的,旨在提升软件的可重用性、可维护性和灵活性。设计模式通常分为三大类:创建型模式、结构型模式行为型模式。以下是常见的23种设计模式及其简介:

一、创建型模式(Creational Patterns)

1. 单例模式(Singleton Pattern)

作用:

确保一个类只有一个实例,并提供全局访问点。

优点:

  • 可以确保某个类在整个程序中只有一个实例,避免内存浪费。
  • 适合管理共享资源(如数据库连接池、配置文件读取等)。

缺点:

  • 隐藏了类的实例化过程,难以进行单元测试。
  • 如果不小心实现,可能会导致线程安全问题。

常见应用场景:

  • 配置管理器、日志管理器、数据库连接池。

2. 工厂方法模式(Factory Method Pattern)

作用:

定义一个创建对象的接口,但由子类决定实例化哪一个类。

优点:

  • 将对象的创建过程延迟到子类,符合开闭原则。
  • 可以避免复杂的构造函数和依赖。

缺点:

  • 需要大量的子类来实现具体的工厂方法。
  • 增加了系统的复杂性。

常见应用场景:

  • UI组件库中的不同按钮、操作系统中的不同UI元素。

3. 抽象工厂模式(Abstract Factory Pattern)

作用:

提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。

优点:

  • 将多个产品族的创建逻辑集中管理,避免产品家族之间的耦合。
  • 符合开闭原则,可以在不修改代码的情况下增加新的产品族。

缺点:

  • 增加了系统的复杂度,使用时需要额外的工厂类。
  • 如果产品家族较多,可能会导致工厂类数量暴增。

常见应用场景:

  • 跨平台UI组件库、操作系统的硬件抽象层。

4. 建造者模式(Builder Pattern)

作用:

使用多个简单的对象一步步构建成一个复杂的对象。

优点:

  • 客户端不需要了解构建细节,简化了对象的创建过程。
  • 可以使用不同的建造方式来生成不同类型的对象。

缺点:

  • 对于复杂对象的构建来说,可能需要很多的“建造者”类,导致代码冗长。
  • 不适合在对象很简单时使用。

常见应用场景:

  • HTML文档生成、复杂对象的序列化(如XML、JSON)。

5. 原型模式(Prototype Pattern)

作用:

通过复制现有的实例来创建新的对象,而不是通过构造器创建。

优点:

  • 可以通过复制现有对象,避免重复创建对象的开销。
  • 对象的创建和初始化过程较为复杂时,原型模式能够减少构建的复杂性。

缺点:

  • 需要为对象定义“克隆”接口。
  • 对象中的引用类型成员可能导致浅拷贝问题。

常见应用场景:

  • 需要重复创建大量相似对象时(如图形对象、数据库记录的复制)。

二、结构型模式(Structural Patterns)

1. 适配器模式(Adapter Pattern)

作用:

将一个类的接口转换成客户端期望的接口,使得两个不兼容的接口可以工作。

优点:

  • 适配器模式可以帮助老代码与新代码兼容。
  • 提高系统的灵活性,增加可重用性。

缺点:

  • 增加了一层额外的接口,可能导致系统结构复杂化。
  • 如果接口差异过大,适配器会变得很复杂。

常见应用场景:

  • 旧系统与新系统的接口适配,第三方库接口的适配。

2. 桥接模式(Bridge Pattern)

作用:

通过将抽象部分和实现部分分离,使得两者可以独立变化。

优点:

  • 提高了系统的灵活性,允许独立变化的部分不再耦合。
  • 遵循了开闭原则,方便扩展。

缺点:

  • 需要在系统中增加更多的类。
  • 如果抽象层次过多,可能导致设计复杂。

常见应用场景:

  • 图形绘制系统,设备驱动程序。

3. 组合模式(Composite Pattern)

作用:

通过递归组合来构建对象的树形结构,从而使得客户端可以像处理单个对象一样处理组合对象。

优点:

  • 客户端可以一致地对待单个对象和组合对象。
  • 增加了系统的可扩展性,支持新的组件类型。

缺点:

  • 设计较为复杂,尤其是当树形结构过深时。
  • 很难控制所有组合对象的行为。

常见应用场景:

  • 文件系统(文件夹和文件结构)、GUI界面组件。

4. 装饰器模式(Decorator Pattern)

作用:

动态地给对象添加额外的功能,而不改变其结构。

优点:

  • 通过装饰器,可以在不修改现有类的情况下增强功能。
  • 装饰器可以灵活叠加,避免了子类过多的问题。

缺点:

  • 增加了系统的复杂度,尤其是当装饰器层数较多时。
  • 装饰器链可能会导致性能开销。

常见应用场景:

  • Java I/O中的装饰器(例如:BufferedReader、FileReader等组合)。

5. 外观模式(Facade Pattern)

作用:

为复杂的子系统提供一个统一的接口,使得子系统的使用更简便。

优点:

  • 降低了系统的复杂度,通过简单的接口隐藏复杂的实现。
  • 促进了子系统之间的解耦。

缺点:

  • 如果过度依赖外观类,可能会忽略子系统中有用的功能。
  • 系统扩展性差,所有功能都通过外观类暴露。

常见应用场景:

  • 家庭影院、复杂框架的封装、第三方API的简化接口。

6. 享元模式(Flyweight Pattern)

作用:

通过共享对象来有效地支持大量的细粒度对象,减少内存占用。

优点:

  • 可以节省大量内存,提高系统性能。
  • 通过共享的方式,避免重复创建相同的对象。

缺点:

  • 享元模式要求对象不可变,无法灵活修改。
  • 需要管理共享对象池,增加了复杂度。

常见应用场景:

  • 游戏中相同类型的对象(如敌人、子弹)共享资源。

7. 代理模式(Proxy Pattern)

作用:

为其他对象提供代理,以控制对对象的访问。

优点:

  • 代理可以为真实对象提供保护,延迟加载等功能。

  • 增加了系统的灵活性和控制性。

缺点:

  • 增加了代码复杂度和层次。

  • 代理的使用可能会影响性能。

常见应用场景:

  • 远程代理(远程服务调用)、虚拟代理(延迟加载)、保护代理(权限控制)。

三、行为型模式(Behavioral Patterns)

1. 责任链模式(Chain of Responsibility Pattern)

作用:

通过将请求沿着处理链传递,直到有对象处理它为止。

优点:

  • 责任链模式可以避免多个处理器之间的硬耦合,增加灵活性。
  • 可以动态地增加处理环节。

缺点:

  • 不保证请求最终能被处理,可能导致请求失败。
  • 责任链过长时可能导致性能问题。

常见应用场景:

  • 日志记录、审批流程、过滤器链。

2. 命令模式(Command Pattern)

作用:

将请求封装成对象,从而让你可以使用不同的请求、队列和日志请求,支持可撤销操作。

优点:

  • 支持命令的撤销、重做操作。
  • 可以将请求发送者与接收者解耦。

缺点:

  • 需要为每个请求创建命令类,增加了类的数量。
  • 增加了系统的复杂性。

常见应用场景:

  • GUI界面的按钮点击、遥控器控制系统、事务管理。

3. 解释器模式(Interpreter Pattern)

作用:

给定一个语言,定义它的文法,并提供一个解释器来解释句子。

优点:

  • 提供了一种易于扩展的方式来处理复杂的语言规则。
  • 易于将新规则添加到现有的解释器中。

缺点:

  • 如果文法复杂,解释器会变得非常复杂。
  • 解析性能可能成为瓶颈。

常见应用场景:

  • SQL解析器、正则表达式引擎、编程语言解释器。

4. 迭代器模式(Iterator Pattern)

作用:

提供一种方法来顺序访问集合中的元素,而不暴露集合的内部表示。

优点:

  • 可以统一访问集合元素的方式。
  • 使得集合类内部的实现细节对外部透明。

缺点:

  • 如果集合是动态变化的,迭代器可能会失效。
  • 需要为每种集合类实现相应的迭代器。

常见应用场景:

  • 集合类的遍历(如ArrayList、LinkedList的迭代器)。

5. 中介者模式(Mediator Pattern)

作用:

通过定义一个中介者对象来封装一组对象的交互,使得对象不需要直接交互。

优点:

  • 减少了对象之间的耦合。
  • 可以集中控制对象间的交互行为。

缺点:

  • 中介者可能会变得非常复杂。
  • 所有的交互都通过中介者进行,可能导致中介者成为系统的瓶颈。

常见应用场景:

  • 聊天系统、GUI控件的事件处理。

6. 备忘录模式(Memento Pattern)

作用:

在不暴露对象的实现细节的情况下,捕获对象的内部状态,并在之后恢复该状态。

优点:

  • 支持对象状态的恢复(撤销操作)。
  • 可以在对象外部保存状态,便于管理。

缺点:

  • 需要大量的存储空间来保存备忘录。
  • 可能会导致程序设计的复杂度增加。

常见应用场景:

  • 游戏存档、撤销操作、历史记录管理。

7. 观察者模式(Observer Pattern)

作用:

当一个对象状态发生改变时,所有依赖于它的对象都会自动得到通知并更新。

优点:

  • 观察者和主题对象之间解耦。
  • 可以动态地增加或删除观察者。

缺点:

  • 如果有大量的观察者,可能会导致性能问题。
  • 可能会导致不必要的多次更新。

常见应用场景:

  • GUI界面的事件处理、消息发布/订阅系统。

8. 状态模式(State Pattern)

作用:

允许对象在内部状态改变时改变其行为,表现得像是改变了一个类。

优点:

  • 可以清晰地表示对象的状态变化,避免使用多重条件语句。
  • 增强了系统的可维护性。

缺点:

  • 增加了类的数量。
  • 状态转换需要小心管理。

常见应用场景:

  • 状态机(如订单、游戏角色的状态管理)。

9. 策略模式(Strategy Pattern)

作用:

定义一系列算法,并将每个算法封装起来,使得它们可以互换。

优点:

  • 可以在运行时切换算法。
  • 避免了多个条件语句和复杂的算法逻辑。

缺点:

  • 需要创建多个策略类。
  • 客户端需要知道策略的选择和管理。

常见应用场景:

  • 排序算法的选择、支付方式选择(如支付宝、微信支付)。

10. 模板方法模式(Template Method Pattern)

作用:

定义一个算法的骨架,并允许子类实现算法的某些步骤。

优点:

  • 可以在不改变算法结构的情况下,提供灵活的定制点。
  • 提高了代码的可复用性。

缺点:

  • 过多的模板方法可能导致代码过于复杂。
  • 子类需要根据父类的规定方法进行实现。

常见应用场景:

  • 游戏框架中的初始化和更新方法,文件处理。

11. 访问者模式(Visitor Pattern)

作用:

允许你在不改变元素类的前提下,定义作用于元素的操作。

优点:

  • 可以很容易地为不同的元素对象增加新操作。
  • 让操作和数据结构分离,便于扩展。

缺点:

  • 增加了访问者类的复杂度。
  • 如果元素类层次结构发生改变,访问者类也需要做相应的修改。

常见应用场景:

  • 复合元素的结构操作、编译器的语法分析。

以上是当下常用的23种设计模式,后面有时间会把其中常用的几种展开聊一聊。

如有错误欢迎指正交流。

公众号:Altma

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值