软件设计模式及其应用
软件设计模式(Software Design Pattern)是一套被反复使用的、多数人知晓的、经过分类编目的代码设计经验的总结。使用设计模式的核心目的在于复用代码提高编码效率、增加代码的可理解性、保证代码的可靠性。
软件设计模式是软件开发的最佳实践之一,在面向对象软件开发过程中被广泛采用。项目中合理地运行设计模式可以解决很多问题,每种模式在实际应用中都有相应的原型与之相对,每种模式都描述了一个在软件开发中不断重复发生的问题,以及对应该原型问题的核心解决方案。
(一)创建型模式
创建型模式主要用于对象的创建过程,它提供了一种创建对象的方式,将对象的创建和使用分离。其特点是隐藏对象的创建逻辑,使代码更加灵活和可维护。常见的创建型模式包括:
单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点。该模式在需要控制资源访问或共享资源时非常有用,如数据库连接池、日志记录器等。通过单例模式,可以避免多次创建相同的对象,从而节省系统资源。
工厂模式(Factory Pattern):定义一个创建对象的接口,让子类决定实例化哪一个类。工厂模式将对象的创建和使用分离,提高了代码的可维护性和可扩展性。在 Java 开发中,使用 JDBC 创建数据库连接时可能用到工厂模式,如
DriverManager
的getConnection
方法,隐藏了不同数据库驱动的实现。抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。该模式适用于需要创建多个相关对象的场景,比如不同操作系统风格的用户界面中控件的组合。
建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。该模式常用于创建具有复杂构造过程的对象,比如在游戏开发中创建复杂的角色对象,通过建造者模式可以一步步地构建角色的各种属性和装备。
原型模式(Prototype Pattern):使用一个已经创建好的对象作为原型,通过克隆这个原型来创建新的对象。该模式适用于创建新对象成本较高的情况,可以避免在创建新对象时重复执行复杂的初始化过程,提高对象创建的效率,比如在图形绘制系统中复制图形对象。
(二)结构型模式
结构型模式主要用于处理类或对象的组合,它描述了如何将类或对象组合成更大的结构。其特点是通过组合不同的类或对象,以满足不同的业务需求。常见的结构型模式包括:
代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。代理模式可以在不改变原始对象的情况下,增加额外的功能,如权限验证、缓存等。在 RPC 框架中,远程代理用于访问远程服务器上的对象。
装饰器模式(Decorator Pattern):在不修改现有对象结构的情况下,动态地给对象添加额外的职责或行为。装饰器模式通过组合的方式,而不是继承的方式来扩展对象的功能,使得代码更加灵活和可维护。在 Java 的 IO 流中广泛应用了装饰器模式,比如
BufferedInputStream
和BufferedOutputStream
可以为基本的字节流添加缓冲功能,提高读写效率。适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以协同工作。适配器模式广泛应用在新旧系统接口转换和第三方库集成中,例如在电商平台,通过适配器模式将不同接口的第三方支付与物流系统集成到统一的流程里。
桥接模式(Bridge Pattern):分离抽象部分和实现部分,分别定义为独立的类层次结构,通过组合关系将它们连接起来,抽象部分定义了高层的业务逻辑和抽象接口,实现部分则负责具体的底层实现细节,当抽象部分或实现部分需要变化时,不会相互影响,提高了系统的可扩展性和可维护性。面向接口的业务逻辑编排体现了桥接模式的特点,例如在消息通知系统中,将通知的业务逻辑(根据不同事件发送不同内容的通知)与具体的通知方式(短信、邮件)实现分离。
组合模式(Composite Pattern):将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。在文件系统的实现中,文件和文件夹可以看作是组合模式的应用,用户可以对单个文件或整个文件夹进行相同的操作。
外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使子系统更加容易使用。外观模式就像小米之家 APP,用户不用分别操作电视、空调、灯光等设备,只需要通过这个统一的控制面板,就能实现对各种设备的控制。具体而言,在分层架构中,表现层可以与业务逻辑外观类对象进行交互,屏蔽子业务的细节,降低层与层之间的耦合度。
享元模式(Flyweight Pattern):主要用于减少创建对象的数量,以降低内存占用和提高性能。它通过共享已经存在的对象来避免创建重复的对象,这些被共享的对象称为享元。Java 的字符串常量池(
String Pool
)一定程度上体现了享元模式的思想,不过与纯粹的享元模式还是有所不同,缺乏显式的享元工厂,对象也非完全共享。
(三)行为型模式
行为型模式主要用于处理对象之间的交互和职责分配,它描述了对象之间的通信方式和协作关系。其特点是以高内聚、低耦合的方式实现行为的封装与传递,借助抽象、多态和委托等技术手段提升系统可扩展性与可维护性。常见的行为型模式包括:
观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时,它的所有依赖者(观察者)都会收到通知并自动更新。在电商平台中,可以使用观察者模式来实现订单状态的实时更新,当订单状态发生变化时,相关的用户、商家和物流系统都能及时收到通知。
策略模式(Strategy Pattern):定义了一系列算法,将每个算法封装起来,并且使它们可以相互替换,策略模式使得算法的变化独立于使用算法的客户端。Java 的
Comparator
接口体现了策略模式的思想,例如工具方法Collections.sort(list, comparator)
中排序算法的替换。模板方法模式(Template Method Pattern):定义一个操作中的算法骨架,将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤,是一种基于继承的代码复用技术。Spring 框架中的
JdbcTemplate
定义了执行数据库操作的模板方法,如查询、更新等操作的基本流程。命令模式(Command Pattern):将请求或操作封装到一个对象中,将发出命令的责任和执行命令的责任分割开,发出命令的对象不需要知道具体的执行逻辑,执行命令的对象只需要专注于命令的执行。在 Java 多线程编程中,
Runnable
对象、等待队列与线程池构成了命令模式的经典场景。责任链模式(Chain of Responsibility Pattern):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。在 Web 开发中,过滤器链是责任链模式的一个典型应用,多个过滤器(如登录验证过滤器、权限检查过滤器、字符编码过滤器等)组成一条链,当请求到达服务器时,会依次经过这些过滤器,每个过滤器根据自身的逻辑对请求进行处理或放行。
迭代器模式(Iterator Pattern):提供了一种方法来顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。它将对集合的遍历和访问逻辑封装在一个迭代器对象中,使得客户端可以通过统一的接口来遍历不同类型的集合,而无需了解集合的具体实现细节。在 Java 中遍历集合类时,经常会用到迭代器模式。
访问者模式(Visitor Pattern):将数据操作和数据结构分离,它允许一个或者多个操作应用到一组对象上,解耦了操作和对象本身,使得在不改变对象结构的前提下,能够方便地定义新的操作。在编译器中,语法树的节点可以看作是元素,而语义分析、代码生成等操作可以看作是访问者。通过访问者模式,可以方便地对语法树进行不同目的的遍历和处理。
备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。它提供了一种状态恢复的机制,使得对象可以方便地回到之前的某个状态,而不需要了解其内部的状态保存和恢复的具体细节。在数据库操作中,事务开始时可以创建一个备忘录来记录数据库的当前状态。如果事务执行过程中出现错误,就可以根据备忘录将数据库恢复到事务开始前的状态,实现事务的回滚。
状态模式(State Pattern):允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。其核心思想是将对象的状态和行为进行分离,每个状态都对应一个具体的状态类,这些状态类可以根据需要相互切换,从而使对象表现出不同的行为。游戏中的角色可能有不同的状态,如站立、奔跑、跳跃、攻击等。使用状态模式可以将每个状态下角色的行为封装在不同的状态类中,方便管理和扩展。
中介者模式(Mediator Pattern):用一个中介对象来封装一系列的对象交互,使各对象不需要显式地相互引用,从而使其耦合松散。其核心思想是将对象之间的多对多交互关系转变为对象与中介者之间的一对多关系,所有对象之间的通信都通过中介者来完成。聊天服务器是中介者模式的一个具体场景,用户之间不直接通信,而是通过聊天服务器来转发消息。
解释器模式(Interpreter Pattern):定义一种语言的语法规则,并创建一个解释器来解释该语言中的句子或表达式。通过这种模式,可以将特定领域的语言或规则转化为计算机能够理解和处理的形式。正则表达式是解释器模式典型的应用场景。
版权声明: 本文为 InfoQ 作者【陈一之】的原创文章。
原文链接:【http://xie.infoq.cn/article/834ddc0c00f1e1a7a74ee491b】。文章转载请联系作者。
评论