天天看点

架构师备战(三)-软件工程(十一) 系统设计之面向对象设计原则

作者:IT动力

我们知道需求规格说明书(SRS)落地之后, 就要开始着手系统设计了,看一下这个系统该如何来设计,并且如何实现。学习系统设计之前,需要先了解系统设计有哪些分类。

系统设计的分类如下

  • 界面设计
  • 结构化设计
  • 面向对象设计(最重要)

1、界面设计

界面设计也叫做人机界面设计,属于系统与用户交互的纽带。而人机界面设计在架构师考试中相对来说考得比较浅,我们了解一下人机界面设计得一些理念即可。

  • 置于用户控制之下
    • 以不强迫用户进入不必要的或不希望的动作的方式来定义交互方式
      • 简单来说,就是用户点了什么,预期的结果就是什么
      • 有些网站有那种您需要点多次才能进去的情况,第一次始终进的是广告,第二次才能看到对应的资源。这就违反了这个原则,从而让用户强制进广告让网站盈利。
    • 提供灵活的交互
    • 允许用户交互可以被中断或者撤销
      • 不然某个操作非常耗时,不小心点错了,但是不能中断,那就是用户体验不好。
    • 当技能级别增加时可以使交互流水化并允许定制交互
    • 使用户隔离内部技术细节
      • 用户不需要了解你用了哪些技术,关注的只是能不能快速使用,所以要对用户隔离技术细节,直接上手操作即可。
    • 设计应允许用户和出现在屏幕上的对象直接交互
  • 减少用户得记忆负担
    • 减少对短期记忆的要求
      • 不可能使用你的系统,还得先看一下帮助文档,那就是用户体验不好
    • 建立有意义的缺省
      • 某些东西不需要用户填,设置默认值可以让用户少填一点
    • 定义直觉性的捷径
      • 定义某些公用的符号 比如放大镜图标就是放大的意思,×符号就是关闭的意思等。
    • 以不断进展的方式揭示信息
  • 保持界面的一致性
    • 允许用户将当前任务放入有意义的语境
    • 在应用系列内保持一致性
    • 如过去的交互模型已建立起了用户期望,除非有迫不得已的理由,不哟啊改变它。

人机界面上设计考察的深度不是很深,了解到这里就可以了。

2、结构化设计

结构化设计分为概要设计和详细设计(一般已经被面向对象设计取代了)。

概要设计:对应的是模块的划分,模块接口的设计。对应后面的集成测试(把各个模块集合起来测接口)。

详细设计:是基于概要设计已经把很多东西分成小的块,也就是分成了对应的函数了,对函数内部进行具体流程的设计或算法的设计就叫做详细设计。一般针对的是模块内。

详细设计的基本思想

  • 抽象化
  • 自顶向下,逐步求精
    • 因为是结构化的,也就是面向过程,所以是自顶向下设计
  • 信息隐蔽
    • 同样是需要去调用接口,而不是直接操作实现类
  • 模块独立(高内聚、低耦合)

高内聚(内聚程度从上到下逐渐降低)

  • 功能内聚(内聚程度最高)
    • 完成一个单一功能,各个部分协同工作,缺一不可。对应单一职责原则,就是一个类实现的功能月单一越好,否则会指责过重,啥都要它做。
  • 顺序内聚
    • 处理袁术相关,而且必须顺序执行
  • 通信内聚
    • 所有处理元素集中在一个数据结构的区域上
  • 过程内聚
    • 处理元素相关,而且必须按也顶的次序执行
  • 瞬时内聚(时间内聚)
    • 所包含的任务必须在同一时间间隔内执行
  • 逻辑内聚
    • 完成逻辑上相关的一组任务
  • 偶然内聚(巧合内聚)
    • 完成一组没有关系或松散关系的任务

低耦合(耦合程度从上到下逐渐升高)

  • 非直接耦合
    • 两个模块直接没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的
  • 数据耦合
    • 一组模块借助参数表传递简单数据
  • 标记耦合
    • 一组模块通过参数传递记录信息(数据结构)
  • 控制耦合
    • 模块之间传递的信息中包含了控制模块内部逻辑的信息
  • 外部耦合
    • 一组模块都访问同一全局变量,而且不是通过参数传递该全局变量的信息
  • 公共耦合
    • 多个模块都访问一个公共数据环境
  • 内部耦合
    • 一个哦快直接访问宁一个模块的内部数据,一个模块不通过正常入口转到另一个魔魁啊内部。两个模块有一部分代码重叠,一个模块多个入口。

高内聚,低耦合,意思就是内聚程度越高越好,耦合程度越低越好。

结构化设计的基本原则

  • 保持模块的大小适中
    • 这个适中的尺度不好确认,也就是说模块的职责不能过重
  • 尽可能减少调用的深度
    • 调用深度过深会导致栈内存占用较多,一般不超过七层,递归除外
  • 多扇入,少扇出
    • 模块的独立性很好,多扇入表示调用该模块的应用比较多。少扇出表示本模块调用其他模块较少,意味着该模块功能比较独立,不依赖其他模块,依赖多了就是高耦合了
  • 单入口,单出口
    • 不容易出错,入口出口都单一
  • 模块的作用域应该在模块之内
    • 尽量使用局部变量,作用域就可控。全局变量可能其他模块也会修改
  • 功能应该是可以预测的

结构化设计这些知识了解就行,不用深究。

3、面向对象设计(重要)

3.1、设计原则

  • 单一职责原则
    • 设计目的单一的类
    • 也就是设计类时,它只做自己该做的时,不要在类里面设计太多的东西,从而达到高内聚,低耦合
  • 开放-封闭原则
    • 对扩展开发,对修改关闭
    • 比如我们新增或修改一个功能时,我们最好新增一个类来操作,把逻辑都写在新的类里面,然后再原来要修改的地方,直接调用这个类的方法。这样就较少了代码的修改,从而减少了出现错误的风险。
    • 再比如:我们设计的时候用接口设计,接口分别有多找那个实现,我们要新增一种实现,就新增一个接口实现类就可以了,然后使用SPI切换一个接口的具体实现。这就是对扩展开放,对修改关闭(尽量的减少直接修改代码)
  • 里氏(Liskov)替换原则
    • 子类可以替换父类
    • 子类继承了父类的所有特性,父类出现的地方可以使用子类替换它。
  • 依赖倒置原则
    • 要依赖于抽象,而不是具体实现。针对接口编成,不要针对实现编程。
    • 为什么针对接口编程就变成了依赖倒置原则呢
      • 因为原本是依赖实现类,现在依赖的是实现类的接口。以前是A->B,A->C, B->D, C->E这种上层调用下层,如果下层的方法改变了,那么上层得跟着改变,特麻烦。面向对象就在上层定义接口,让下层去实现上层的接口。就变成了下层依赖于上层的接口,这样看依赖关系就倒置了。
  • 接口隔离原则
    • 使用多个专用接口比使用单一的总接口要好
  • 组合重用原则
    • 要尽量使用组合,而不是集成关系达到重用目的。
    • 继承是一种紧耦合,而我们不希望紧耦合。不然会导致父类修改了什么,所有的子类都需要改。
  • 迪米特(Demter)原则(最少知识原则)
    • 一个对象应当对其他对象尽可能少的了解
    • 说白了,就是使用private这类关键字,将自己对象的属性封装起来,避免被其他类非法修改。只能通过统一的setter或者getter来进行操作。

3.2、设计模式的概念

什么是模式?

模式通俗来讲就是套路,比如武侠小说跳悬崖之后必有奇遇,这就是一套套路,也是一种模式。

很多时候我们会有一些模式化的东西,却解决一些现有的问题,是一种很不错的策略,这就是设计模式。

设计模式的概念

  • 架构模式(高层次)
    • 软件设计中的高层决策,例如C/S结构就属于架构哦是,架构模式反映了开发软件系统过程中所作的基本设计决策。
  • 设计模式(中层次)
    • 主要关注软件系统的设计,与具体的实现语言无关
  • 惯用法(低层次)
    • 最低层次的模式,关注软件系统的设计与实现,实现时通过某种特定的程序设计语言来描述构建与构建之间的关系。每种编程语言都有它自己特定的模式,即语言的惯用法。例如引用-计数就是C++语言中的一种惯用法。

惯用法和设计模式最大的区别就是是否跟计算机语言相关。

4、小结

从上面我们说明了系统设计的一些概念,也说到了设计模式的概念,上面最重要的就是面向对象的设计原则。接下来就需要详细说明23种设计模式了,下次再写吧!加油!