Trey blog.

读设计模式解析(一)

1.功能分解

分析人员将问题分解成了多个功能步骤。

功能分解存在的问题:

1. 它通常会导致“主”程序负责控制子程序,这是将功能分解为多个子功能的自然结果。最终导致主程序所承受的责任太多了,会产生非常复杂的代码。
2. 它在未来需求出现变化时,或是在对代码合适地改进时,都于事无补。

许多的bug都源于代码的修改

2.需求总在变化

  • 用户对自己需求的看法,会因为与开发人员的讨论以及看到软件新的可能性而发生变化
  • 开发人员对用户问题领域的看法,会在开发的过程中,因为对它更加熟悉而发生变化
  • 软件开发的环境发生了变化

我可能无法知道什么将会变化,但是我能够猜到在哪里会变化

与其抱怨需求总是变化,不如改变开发过程,从而更有效地应对变化。代码可以设计得使需求的变化不至于产生太大影响。代码可以逐步演进,新代码可以影响较少地加入

3.应对变化:使用功能分解

在使用功能分解的同时,使之模块化。模块化有助于提供代码的可理解性,而容易理解将使代码更容易维护。

模块化可能带来的问题:

1. 低内聚
2. 高耦合

内聚性:例程中操作之间联系的紧密程度,内部组成部分之间相互联系的紧密程度。因为例程(或类)中的多个操作联系越紧密,就越容易理解其含义

耦合性:一个例程与其他例程之间联系的紧密程度

软件开发的目标:高内聚,低耦合

不良副作用:或一个数据,后来却对代码的其他地方造成了意想不到的影响(bug)。

在维护和调试的绝大多数时间都被用于努力弄清代码的运作机理、寻找bug和防止出现不良副作用上了,真正的改正时间却相当短。

使用功能分解时,需求变更会对软件开发和维护工作产生极大影响。 这时候,主要的精力都放在函数上了,而对一组函数或者数据的修改会影响到其他函数和数据,并依此类推地影响到其他必须修改的函数。只关注函数,将导致一连串变化,而且难以避免。

4.软件开发中的视角

  • 概念:呈现了所研究领域中的各种概念,得出概念模型时应该很少或者不考虑实现它的软件。这个视角考虑的是:软件需要负责什么?
  • 约定:关注的是软件的接口,而不是实现。这个视角要回答的问题是:怎么使用软件?
  • 实现:这时我们考虑的是代码本身。这个视角要回答的问题是:软件怎样履行自己的责任?

在一个层次上交流,而在另一个层次上执行,这样请求者就无需准确知道具体操作细节了,只需一般性——概念性地知道即可。只要概念不变,请求者就与实现细节的变化隔离开了

5.面向对象范型 —— 使用对象将责任转移到更局部的层次

面向对象范型以对象概念为中心,一切都集中在对象上。编写代码时是围绕对象而非函数进行组织的。

使用对象的优点在于,可以定义自己负责自己的事物。 对象天生就知道自己的类型。对象中的数据能够告诉它自己的状态如何, 而对象中的代码能够使它正确工作。

定义对象

  1. 寻找在问题领域中的实体
  2. 通过查看这些实体需要做些什么,为每个对象确定责任

    对象应该自己负责自己,而且应该清楚地定义责任。

  • 在概念层次上,对象是一组责任
  • 在约定层次上,对象是一组可以被其他对象或对象自己调用的方法 (也称行为)
  • 在实现层次上,对象是代码和数据,以及它们之间的计算交互

类就是对对象行为的定义

  • 对象所包含的数据元素
  • 对象能够操作的方法
  • 访问这些数据元素和方法的方式

对象所属类的一个对象被称为该类的一个实例,创建实例的过程称为实例化

抽象类:定义了其他一些相关类的行为。

具体类:定义了一个概念特定,不变的实现。

封装:通常定义为数据隐藏,但最好将它看作任何形式的隐藏(类型、实现和设计等等)。

继承:一个类继承另一个类,是指它接受了该类的一些或者所有性质。起始类称为基类、 超类、父类或者泛化类,而继承类称为派生类、子类或者特化类。

实例:类的特例(总是一个对象)。类的特殊实例或者实体。每个对象都有自己的状态。因此同一个类型(类)可以有多个对象。

实例化:创建类的一个实例的过程。

接口: 接口与类类似,但是只为其成员提供约定而不提供实现。

多态: 能够用一种方式引用一个类的不同派生类,但获得的行为对应于所引用的派生类

封装的优点

  1. 使用容易,调用者不用担心实现问题。
  2. 可以在不考虑调用者的情况修改实现。调用者和被调用者之间不存在任何依赖关系。
  3. 其他对象对该对象内部是不可见的。

封装什么东西时,必然将使其耦合变松。隐藏实现(即封装它们)有助于松耦合。

对象对自己行为所负的责任越多,控制程序需要负的责任就越少。