设计模式总结
原创
2024-07-27 02:48
27
软件设计模式课程报告 | **姓名** | **彭飞** | | :--------- | :--------------------: | | **学号:** | **14214800889** | | **专业:** | **软件工程** | | **班级:** | **软件21-2bf** | | **院系:** | **信息科学与工程学院** | 二〇二四 年 六月 八日 软件设计模式总结 # 一、创建型模式——工厂模式(Factory Pattern) ## 1.1、设计目的 工厂模式(Factory Pattern)的设计目的是将对象的创建过程与其使用过程分离,提供一种创建对象的接口,让子类决定实例化哪一个类。这一模式通过将实例化操作延迟到子类中实现,从而使得系统更具灵活性和可扩展性 ## 1.2、结构 抽象产品(Product):定义了产品的接口,是具体产品类的基类。 具体产品(ConcreteProduct):实现了抽象产品接口,是被创建的具体实例。 抽象工厂(Creator):声明了工厂方法,用于返回一个抽象产品类型的对象。工厂方法是一个抽象方法,由子类具体实现。 具体工厂(ConcreteCreator):实现了工厂方法,返回一个具体产品实例。  ## 1.3、特征 ` `解耦对象的创建和使用:在没有工厂模式的情况下,创建对象的代码通常直接嵌入到业务逻辑中,这会导致创建和使用之间的紧密耦合。工厂模式通过引入一个专门的工厂类,负责对象的创建,从而解耦了创建和使用的关系,使得代码更加清晰、可维护。 提高代码的可扩展性:通过使用工厂模式,可以方便地引入新的产品类而不需要修改现有的客户端代码。只需扩展工厂类并实现新的产品创建方法,就可以将新产品引入系统。这符合开闭原则(对扩展开放,对修改关闭),提高了代码的可扩展性。 ` `控制实例化过程:工厂模式可以控制实例化过程,使其更加灵活。例如,可以在工厂类中引入缓存机制,控制实例的生命周期,或者根据不同的条件创建不同的产品对象。 简化客户端代码:客户端代码不需要关心具体产品类的实例化过程,只需调用工厂类的创建方法即可。这简化了客户端代码,使其更加简洁易读。 ## 1.4、应用 ` `应用场景:文件解析器 在处理不同类型的文件(如 XML、JSON、CSV 等)时,可能需要使用不同的解析器。工厂模式可以根据文件类型,动态选择合适的文件解析器,从而实现对不同文件格式的支持。 分析: 在一个文件处理系统中,用户可能会上传各种格式的文件。系统需要根据文件的类型,选择相应的解析器进行处理。如果将文件解析的逻辑直接写在业务逻辑中,不仅会导致代码臃肿,而且增加新的文件格式支持时需要修改已有代码,违背开闭原则。 应用工厂模式: 通过引入工厂模式,可以将文件解析器的创建逻辑集中在工厂类中。工厂类根据传入的文件类型,返回相应的解析器对象。这样,当需要增加新的文件格式支持时,只需扩展新的解析器类和对应的工厂逻辑,而不需要修改现有的业务代码。 优点: 客户端代码不需要关心具体的文件解析器实现,代码更加简洁、可维护。 新增文件格式时,只需扩展新的解析器类和工厂逻辑,符合开闭原则。 实现 文件解析器接口  具体的文件解析器:实现不同类型的文件解析器,如 XML、JSON 和 CSV 解析器。    文件解析器工厂类:定义一个工厂类,根据文件类型返回相应的文件解析器。  客户端代码:客户端代码只需要调用工厂类获取相应的解析器,并进行文件解析。  运行结果:  ## 1.5总结 设计模式的运用使得代码更加清晰、易于理解和扩展。工厂模式尤其适用于对象的创建过程相对复杂、需要隐藏具体实现细节的情况,有助于降低代码的耦合度,提高了代码的可维护性和可扩展性。 面向对象编程的思想能够更好地将现实世界的问题抽象成程序中的对象和类,从而更加直观地理解和解决问题。 在编程过程中,对异常情况的处理尤为重要,可以提高程序的健壮性和用户体验。 # **二、结构性模式——适配器模式(Adaptor Pattern)** ## 2.1、设计目的 适配器允许两个不兼容的接口协同工作。这是适配器的实际定义。接口可能不兼容,但内部功能应符合需求。适配器设计模式允许其他不兼容的类通过将一个类的接口转换为客户端所需的接口来协同工作。 适配器设计模式解决了以下问题: 如何重用没有客户端所需接口的类? 具有不兼容接口的类如何协同工作? 如何为类提供替代接口? 通常,一个(已经存在的)类不能重用,只是因为它的接口不符合客户端所需的接口。 适配器设计模式描述了如何解决此类问题: 定义一个单独的类,该类将类的(不兼容)接口转换为客户端所需的另一个接口。adapteradapteetarget 通过一个来处理(重用)没有所需接口的类。adapter 此模式的关键思想是通过一个单独的接口来工作,该接口在不更改(已存在的)类的情况下适应它。adapter 客户端不知道他们是直接使用类还是通过没有接口的类使用。targetadaptertarget ## 2.2、结构 目标接口(Target):定义客户需要的接口。 适配者类(Adaptee):定义一个已经存在的接口,需要适配。 适配器类(Adapter):通过继承适配者类,并实现目标接口,将适配者接口转换成目标接口。  ## 2.3、特征 接口转换:适配器模式可以将一个类的接口转换为客户期望的另一个接口,从而实现原本由于接口不兼容而无法一起工作的类可以协同工作。 复用性:通过适配器模式,可以复用现有的类,使其适配新的接口需求,而不需要修改原始类的代码。 灵活性:适配器模式提高了系统的灵活性,使得在不改变现有类的情况下,通过增加适配器类实现接口的转换。 两种实现方式:适配器模式有类适配器和对象适配器两种实现方式。类适配器通过继承实现,而对象适配器通过组合实现。 遵循开闭原则:适配器模式遵循开闭原则(对扩展开放,对修改关闭),通过增加适配器类来扩展系统功能,而不需要修改已有类。 ## 2.4、应用 ` `应用场景:不同格式的数据转换 在处理不同格式的数据时,可能需要将一种格式的数据转换为另一种格式。通过适配器模式,可以实现数据格式的转换。 详细分析: 例如,一个数据处理系统需要将 JSON 格式的数据转换为 XML 格式的数据。直接在业务代码中处理数据格式转换,不仅会增加代码复杂度,还会降低代码的可维护性。 应用适配器模式: 通过创建一个适配器类,将 JSON 数据转换为 XML 数据格式。这样,数据处理模块可以通过统一的接口处理不同格式的数据,而不需要关心数据格式的差异。 优点: 数据处理逻辑与数据格式转换逻辑解耦,代码更加清晰、易维护。 新增或修改数据格式时,只需修改或新增适配器类,而不需要修改数据处理逻辑。 实现 数据转换接口:定义一个接口,所有的具体数据转换器都需要实现这个接口  具体的数据转换器:实现不同类型的数据转换器,例如将 JSON 数据转换为 XML 数据。   适配器类:创建一个适配器类来封装数据转换逻辑。  客户端代码:客户端代码通过适配器类进行数据格式转换,而不需要关心具体的转换实现。  运行结果:  ## 2.5、总结 适配器模式通过将一个类的接口转换为客户期望的接口,实现了不同接口之间的兼容性和协同工作。其主要特点是接口转换、提高复用性和灵活性,并遵循开闭原则。适配器模式广泛应用于第三方库集成、遗留系统整合、数据格式转换和 GUI 组件适配等场景。通过合理应用适配器模式,可以在不修改现有代码的情况下,实现系统的扩展和功能的增强,从而提高开发效率和代码质量。 # **三、结构型模式——桥接模式(Bridge Pattern)** ## 3.1设计目的 桥接模式的设计目的是将抽象部分与它的实现部分分离,使它们都可以独立地变化。通过这种方式,可以将一个大类或者一系列紧密关联的类分解为多个更为灵活、可独立变化的部分,从而减少类间的耦合,增强系统的可扩展性和灵活性。 ## 3.2、结构 抽象类(Abstraction):定义抽象部分的接口,并持有一个对实现部分的引用。 扩展抽象类(RefinedAbstraction):继承自抽象类,扩展抽象部分的接口。 实现接口(Implementor):定义实现部分的接口,该接口不一定与抽象部分的接口完全一致,但一般提供基本的操作接口。 具体实现类(ConcreteImplementor):实现实现接口,定义具体的实现。  ## **3.3、特征** 分离抽象和实现:桥接模式将抽象部分与实现部分分离,使它们可以独立地变化和扩展。 提高系统的可扩展性:抽象和实现的分离使得系统更易于扩展,不需要修改现有代码。 降低耦合度:抽象和实现的独立变化降低了它们之间的耦合度,提高了系统的灵活性。 组合优于继承:通过组合而非继承来实现系统功能,可以更灵活地选择和替换实现部分。 ## **3.4、应用** 应用场景:数据库访问层 在一个数据库访问层中,可能需要支持多种数据库(如 MySQL、Oracle、SQL Server 等),并且需要提供多种访问方式(如 JDBC、JPA、Hibernate 等)。直接使用继承将导致类的爆炸式增长,不易维护。 详细分析: 例如,一个数据库访问层需要支持多种数据库和多种访问方式。如果将每种数据库和访问方式的组合都实现为一个类,将会导致类的数量急剧增加,不利于系统的扩展和维护。 应用桥接模式: 通过桥接模式,可以将数据库的抽象部分(如增删改查操作)与访问方式的实现部分(如 JDBC、JPA)分离。抽象部分定义数据库操作的接口,实现部分定义访问方式的接口。具体的数据库操作类通过组合的方式持有访问方式实现的引用,从而实现数据库操作和访问方式的灵活组合。 优点: 数据库操作和访问方式的实现可以独立变化,降低了系统的耦合度。 新增数据库类型或访问方式时,只需增加相应的类,而不需要修改现有代码。 实现 定义数据库操作:接口定义一个数据库操作接口,包含基本的增删改查操作。  定义访问方式接口:定义一个访问方式接口,包含具体的数据库访问方法。  具体的访问方式实现:实现不同的访问方式,例如 JDBC 和 JPA。   抽象的数据库操作类:抽象的数据库操作类通过组合的方式持有访问方式实现的引用。  具体的数据库操作类:具体的数据库操作类实现数据库操作接口,并使用组合的访问方式实现进行操作。  客户端代码:客户端代码通过组合具体的数据库操作和访问方式实现进行操作。  运行结果:  ## 3.5、总结 桥接模式通过将抽象部分与实现部分分离,使它们可以独立地变化,从而提高系统的灵活性和可扩展性。其主要特点是分离抽象和实现、提高系统的可扩展性、降低耦合度以及组合优于继承。桥接模式广泛应用于图形绘制系统、数据库访问层、消息发送系统和文件操作系统等场景。通过合理应用桥接模式,可以在不修改现有代码的情况下,实现系统的扩展和功能的增强,从而提高开发效率和代码质量。 # **四、行为型模式——策略模式(Strategy Pattern)** ## 4.1、设计目的 策略模式的设计目的是定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式使得算法可以独立于使用它的客户端变化。通过这种方式,可以使得客户端在不改变其代码的情况下,更改算法或行为。 ## 4.2、结构 上下文(Context):上下文类用于维护对某个策略对象的引用,上下文类通过这个引用调用策略类中的算法。 策略接口(Strategy):策略接口定义了一系列算法中的一个通用接口,每个具体策略类实现这个通用接口。 具体策略类(ConcreteStrategy):具体策略类实现了策略接口,提供了具体的算法实现。  ## 4.3、特征 封装变化:将算法的实现细节封装在具体策略类中,使得它们可以独立于上下文类变化。 可扩展性强:通过新增具体策略类来扩展新算法,而不需要修改现有代码。 消除冗长的条件分支:通过使用策略模式,可以避免在客户端代码中使用大量的条件分支语句。 提高代码复用性:不同的策略类可以复用相同的算法接口。 ## 4.4、应用 应用场景:需要对文本进行排序,并支持多种排序算法(如按字母顺序、按长度排序、按词频排序等)。 详细分析:在文本排序系统中,不同的排序算法具有不同的实现逻辑。如果在上下文类中实现所有排序算法,会导致代码复杂且难以维护。 应用策略模式:通过策略模式,将不同的排序算法实现为具体策略类,并定义一个排序算法的接口。上下文类通过持有排序算法接口的引用,可以在运行时动态选择并执行具体的排序算法。 优点:新增排序算法时,只需增加相应的具体策略类,不需要修改现有代码;上下文类的代码更加简洁,可读性更强。 实现 排序算法接口:首先定义一个排序算法接口,所有具体的排序算法都需要实现这个接口。  具体的排序算法:实现不同的排序算法,例如按字母顺序排序、按长度排序和按词频排序。    上下文类:上下文类持有排序算法接口的引用,并提供一个方法来设置排序算法。  客户端代码:客户端代码可以在运行时选择并执行不同的排序算法。  运行结果:  ## 4.4、总结 策略模式通过将算法的实现细节封装在具体策略类中,使得它们可以独立于上下文类变化,从而提高系统的灵活性和可扩展性。其主要特点是封装变化、可扩展性强、消除冗长的条件分支和提高代码复用性。策略模式广泛应用于数据压缩、支付系统、旅行预定系统和文本排序等场景。通过合理应用策略模式,可以在不修改现有代码的情况下,实现算法或行为的动态选择和扩展,从而提高开发效率和代码质量。 ** # 五、行为型模式——责任链模式(Chain Of Responsibility Pattern) ## 5.1、设计目的 责任链模式的设计目的是避免请求的发送者与多个请求处理者耦合在一起,将这些处理者串联成一条链,并沿着这条链传递请求,直到有一个处理者处理它。通过这种方式,可以使得多个对象都有机会处理请求,从而实现请求的灵活分配和处理。 ## 5.2、结构 处理者接口(Handler):定义一个处理请求的接口,包含一个指向下一个处理者的引用,以形成链条。 具体处理者)ConcreteHandler):实现 Handler 接口,处理请求,如果不能处理请求,则将请求转发给下一个处理者。 客户端(Client):创建具体处理者对象并配置责任链,向责任链中的第一个处理者对象提交请求。  ## 5.3、特征 解耦请求的发送者和处理者:通过将处理者串联成一条链,使得请求的发送者和处理者之间的耦合降低。 灵活的链式处理:请求沿着链条传递,直到有一个处理者处理它;如果一个处理者不能处理请求,可以将请求转发给下一个处理者。 动态组合处理者:处理者的组合可以在运行时动态变化,客户端无需关心处理者的具体实现。 增强系统的可扩展性:可以通过增加新的具体处理者类来扩展系统功能,而不需要修改现有代码。 ## 5.4、应用 应用场景:在表单验证系统中,不同的表单字段(如用户名、密码、邮箱等)需要进行不同的验证。 详细分析:表单验证系统中,不同的表单字段需要进行不同的验证,如果一个字段的验证失败,则将验证请求传递给下一个字段进行处理。如果直接在表单字段中实现所有验证逻辑,会导致代码复杂且难以维护。 应用责任链模式:通过责任链模式,将不同的表单验证逻辑实现为具体处理者类,并定义一个处理者接口。表单字段通过持有处理者接口的引用,可以在运行时动态选择并执行具体的表单验证逻辑。 优点:新增表单验证逻辑时,只需增加相应的具体处理者类,不需要修改现有代码;表单字段的代码更加简洁,可读性更强。 ## 5.5、总结 责任链模式通过将请求的处理者串联成一条链,使得请求的发送者与多个请求处理者之间的耦合降低,从而提高系统的灵活性和可扩展性。其主要特点是解耦请求的发送者和处理者、灵活的链式处理、动态组合处理者和增强系统的可扩展性。责任链模式广泛应用于事件处理、权限管理、请求处理系统和表单验证等场景。通过合理应用责任链模式,可以在不修改现有代码的情况下,实现请求处理逻辑的动态选择和扩展,从而提高开发效率和代码质量。 # 6.学习心得 设计模式(Design pattern): 是软件开发经验的总结,是软件设计中常见问题的典型解决方案。每个模式都像一个蓝图,您可以自定义以解决代码中的特定设计问题。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。 设计模式的目的有以下几个: 1\. 代码重用性 (即:相同功能的代码,不用多次编写) 2\. 可读性 (即:编程规范性, 便于其他程序员的阅读和理解) 3\. 可扩展性 (即:当需要增加新的功能时,非常的方便,称为可维护) 4\. 可靠性 (即:当我们增加新的功能后,对原来的功能没有影响) 5\. 使程序呈现高内聚,低耦合的特性 设计模式有7大原则,目的只有一个:降低对象之间的耦合,增加程序的可复用性、可扩展性和可维护性。 ## 6.1、设计模式在软件设计中的重要性 解决常见问题:设计模式提供了一套经过验证的解决方案,可以高效地解决软件开发中常见的问题。例如,工厂模式解决了对象创建的复杂性,适配器模式解决了接口不兼容的问题。通过学习和应用这些模式,我们能够迅速找到问题的解决办法,提高开发效率。 提高代码质量:设计模式能够显著提高代码的可读性、可维护性和可扩展性。例如,责任链模式可以让请求的处理更加灵活,不同的处理者之间松耦合,增加了系统的可扩展性和维护性。这样的设计使得代码更加清晰,易于理解和修改。 促进团队协作:设计模式为团队提供了一种共同的语言和标准,使得团队成员之间能够更好地沟通和协作。例如,当团队成员提到“使用单例模式”时,所有人都能迅速理解这个模式的目的和实现方式,从而减少了沟通成本,提高了工作效率。 增强系统稳定性:通过设计模式,可以构建更加稳健的系统。例如,策略模式可以在不修改原有代码的情况下,通过新增策略来扩展系统功能,减少了代码修改带来的风险。设计模式帮助我们构建出更加稳定、可靠的软件系统。 ## 6.2、对面向对象程序设计和开发的认识提升 通过学习设计模式,我对面向对象程序设计和开发有了更加深入的认识和理解。 理解和应用设计原则:设计模式的核心思想基于面向对象设计原则,如单一职责原则、开闭原则等。在实际开发中,通过应用这些原则,我能够设计出更加模块化、低耦合、高内聚的系统结构。这样的设计不仅提高了代码的质量,还大大简化了维护和扩展的难度。 提高代码复用性:设计模式强调代码的复用性。例如,装饰器模式可以在不改变原有代码的基础上,为对象添加新的功能。这使得我们能够重用已有的代码,减少重复劳动,提高开发效率。 增强系统的灵活性:设计模式强调系统的灵活性和可扩展性。例如,桥接模式通过将抽象部分与实现部分分离,使得它们可以独立变化。这种灵活性使得系统在面对需求变更时,能够迅速适应,而无需大规模重构。 系统化的思维方式:设计模式培养了我系统化的思维方式。在面对复杂问题时,我能够从全局出发,系统地分析问题,设计出合理的解决方案。这样的思维方式不仅提高了我的设计能力,还增强了解决复杂问题的信心和能力。 ## 6.3、学以致用 多实践:在实际项目中主动寻找应用设计模式的机会,通过实践加深理解,提升应用能力。 总结和反思:项目结束后进行总结和反思,记录经验和教训,不断改进设计模式的应用。 灵活应用:根据具体需求灵活调整设计模式的实现,理解核心思想,设计最合适的解决方案。 ## 6.4、模式之思维导图 设计模式根据其意图或目,分为三大类:创建型模式【5个】、结构型模式【7个】、行为型模式【11个】 
评 论
目录