当前位置: 首页 > news >正文

面向可复用性和可维护性的设计模式 课程学习总结

什么是设计模式

设计模式:在软件设计中给定上下文中常见问题的通用的、可重用的解决方案。

设计模式分类

1. 创建型模式——Creational patterns

关注对象创建的过程

1.1 工厂方法模式

定义用于创建对象的接口,但让子类决定要实例化哪个类。工厂方法允许类将实例化推迟到子类。

应用场景:当client不知道要创建哪个具体类的实例,或者不想在client代码中指明要具体创建的实例时,用工厂方法。

优点:无需将特定于应用程序的类绑定到代码中。代码仅处理接口,所以它可兼容其他子类。

缺点:增加代码量,需要额外增加一个Creator类及其子类。

2. 结构型模式——Structural patterns

处理类或对象的组合

2.1 适配器模式

将某个类/接口转换为client期望的其他形式

应用场景:需要在新系统中重用一个不兼容的老组件

在这里插入图片描述

如上图所示,为了实现Shape的display方法,对先前已存在的类—LegacyRectangle中的diaplay方法进行了重用

优点:实现了对已有类的大限度复用,避免“重新造轮子”。

缺点:适配器模式会引入额外的类和代码,这可能会增加系统的复杂性。此外,适配器模式有时会被用来掩盖设计上的问题,而不是解决它们。例如,适配器可能被用来连接不兼容的接口,但这可能是由于设计不良或缺乏整体架构考虑造成的。使用适配器模式可能会使得根本问题被忽视。

2.2 装饰器模式

实现子类特性的任意组合

应用场景:想要对子类实现多个特性的堆叠

在这里插入图片描述

上图为一个应用实例,通过逐层调用装饰器进行包装,实现特性的组合

优点:

  1. 动态扩展对象功能:装饰器模式允许在运行时动态地添加功能,而无需修改对象的类。这使得可以根据需要灵活地增加或移除功能。
  2. 遵循单一职责原则:每个装饰器类都专注于一个特定的功能扩展。这使得每个类的职责更加单一和明确,易于维护和理解。
  3. 替代继承:通过组合而不是继承来扩展对象的功能,避免了类爆炸(class explosion)问题。继承会导致大量的子类,而装饰器模式则通过不同装饰器的组合来实现相同的效果。
  4. 灵活性和可组合性:多个装饰器可以组合使用,以创建复杂的功能扩展。这种组合方式提供了极大的灵活性,允许以多种方式排列和组合装饰器。
  5. 透明性:客户端可以透明地使用装饰器,而无需知道对象被装饰了。装饰器模式对客户端是透明的,客户端代码无需修改即可使用增强功能的对象。

缺点

  1. 增加代码复杂性:虽然装饰器模式提供了灵活性,但也增加了系统的复杂性。尤其是在装饰器链较长时,调试和排查问题可能变得困难。
  2. 较多的小类:由于每个具体装饰器都是一个独立的小类,这可能导致系统中类的数量增加,从而增加维护和管理的难度。

3. 行为类模式——Behavioral patterns

描述类或对象交互和分配责任的方式。

3.1 策略模式

对于特定的任务存在不同的算法,客户端可以在运行时根据动态上下文在算法之间切换。

应用场景:为不同的实现算法构造抽象接口,利用delegation,运行时动态传入client倾向的算法类实例

在这里插入图片描述

如上图所示,在使用ShoppingCart中的pay方法时,可以根据需要传入算法策略的类型,从而实现不同的操作

优点

  1. 开闭原则:策略模式遵循开闭原则(OCP),允许你在不修改现有代码的情况下引入新的策略。新策略的添加不会影响到现有的策略类和上下文类。
  2. 消除条件判断:策略模式通过使用多态消除了在客户端代码中使用条件判断来选择算法的需求。客户端代码不需要通过条件语句来决定使用哪种算法,而是通过策略接口调用对应的算法。
  3. 提高代码的灵活性和可维护性:由于策略模式将算法封装在独立的类中,算法的实现可以独立于其上下文类进行修改。这使得代码更易于理解、维护和扩展。

缺点

  1. 增加对象数量:策略模式会引入大量的策略类,如果策略的数量很多,类的数量也会显著增加。这可能导致代码库变得复杂,管理起来更困难。
  2. 客户端必须了解不同的策略:客户端必须知道不同策略之间的区别,并且需要了解如何选择合适的策略。这增加了客户端代码的复杂性。

3.2 模板模式

做事情的步骤一样,但具体方法不同

应用场景:共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现

优点:实现了代码的复用,减少冗余代码量

缺点:基类中定义的算法骨架是固定的,子类只能修改其中的部分步骤。如果需要修改算法的整体结构,必须修改基类,这可能违背开闭原则(OCP)。

3.3 迭代器模式

客户端希望遍历被放入容器/集合类的一组ADT对象,无需关心容器的具体类型

应用场景:让自己的集合类实现Iterable接口,并实现自己的独特Iterator迭代器(hasNext, next, remove),允许客户端利用这

个迭代器进行显式或隐式的迭代遍历

以下是代码示例

public class Pair<E> implements Iterable<E> {private final E first, second;public Pair(E f, E s) { first = f; second = s; }public Iterator<E> iterator() {return new PairIterator();}private class PairIterator implements Iterator<E> {private boolean seenFirst = false, seenSecond = false;public boolean hasNext() { return !seenSecond; }public E next() {if (!seenFirst) { seenFirst = true; return first; }if (!seenSecond) { seenSecond = true; return second; }throw new NoSuchElementException();}public void remove() {throw new UnsupportedOperationException();}}
}

3.4 Visitor模式

将数据和作用于数据上的某种特定操作分离开来

应用场景:为ADT预留一个将来可扩展功能的“接入点”,外部实现的功能代码可以在不改变ADT本身的情况下通过delegation接入ADT

优点

  1. 易于增加新的操作:通过添加新的访问者类,可以在不修改对象结构的情况下定义新的操作。这使得系统更易于扩展,符合开放/封闭原则(OCP)。
  2. 集中相关行为:访问者模式将相关的行为集中在一个访问者类中,而不是分散在对象类中。这使得行为更容易理解和维护。

缺点

违反单一职责原则:访问者模式将多个不相关的操作集中到访问者类中,可能违反单一职责原则。每个访问者类通常实现多个方法,这些方法可能具有不同的目的和逻辑。

相关文章:

  • 基于java实现图片中任意封闭区域识别
  • NSSCTF-Web题目4
  • Bentham Science药学全文期刊库文献在家轻松下载
  • Java开发-面试题-0001-String、StringBuilder、StringBuffer的区别
  • Gir clone 设置代理与错误
  • [每日一练]查询从不订购的客户(标量子查询)
  • 数据结构——二叉树的实现
  • opencv进阶 ——(七)图像处理之寸照换背景
  • 基于python flask的旅游数据大屏实现,有爬虫有数据库
  • 算法的时间与空间复杂度
  • 【C++面试100问】第八十五问:有了const,C++11为什么还要引入constexpr
  • 【busybox记录】【shell指令】readlink
  • Google发布的CAT3D,在1分钟内,能够从任意数量的真实或生成的图像创建3D场景。
  • 基于STM32+NBIOT(BC26)设计的物联网观赏鱼缸
  • 【前端每日基础】day27——小程序开发
  • Google 是如何开发 Web 框架的
  • 0基础学习移动端适配
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • ES6系列(二)变量的解构赋值
  • express.js的介绍及使用
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • TCP拥塞控制
  • webpack入门学习手记(二)
  • 前嗅ForeSpider教程:创建模板
  • 如何利用MongoDB打造TOP榜小程序
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 探索 JS 中的模块化
  • 正则与JS中的正则
  • 通过调用文摘列表API获取文摘
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • (1)Jupyter Notebook 下载及安装
  • (23)Linux的软硬连接
  • (4)STL算法之比较
  • (9)目标检测_SSD的原理
  • (CVPRW,2024)可学习的提示:遥感领域小样本语义分割
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (二)linux使用docker容器运行mysql
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (七)Knockout 创建自定义绑定
  • (三分钟)速览传统边缘检测算子
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (循环依赖问题)学习spring的第九天
  • **CI中自动类加载的用法总结
  • ./configure,make,make install的作用
  • .apk文件,IIS不支持下载解决
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .net framework 4.0中如何 输出 form 的name属性。
  • .Net OpenCVSharp生成灰度图和二值图
  • .net 生成二级域名
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .NET中 MVC 工厂模式浅析
  • /bin/bash^M: bad interpreter: No such file ordirectory