软件设计师 | 面向对象
面向对象 = 对象 + 分类 + 继承 + 通过消息的通信
# 什么是面向对象
“我去给你打杯水。”我们分别从面向过程的角度和面向对象的角度来分析这句话。
面向过程:“我”和“你”这两个主体都参与到了“去打水”这件事中。我们是围绕着“打杯水”去分析的。
面向对象:我们先将这句话尽可能的分解出多个对象,这句话中“我”、“你”、“水”、“装水的容器”、“打水的地点”。这些都是我们通过这句话分解出来的对象,我们可以将这些对象进行分类、封装,比如这句话中的“我”和“你”其实再抽象可以抽象为“参与者”,我们在这么分析了之后,对这句话的理解就转换为以对象为主体的面向对象思维了,这个时候我们再去通过实例化对应的具体类就可以代码开发了。
# 面向对象基本概念
属性 = 状态 = 数据 = 成员变量
方法 = 行为 = 操作 = 成员函数
# 对象
对象是基本的运行时的实体,它既包括数据,也包括作用于数据的操作。在对象内的操作通常称为方法。
对象是构成世界的一个独立单位,它具有自己的静态特征和动态特征,事物的静态特征用对象的属性表示,动态特征(即事物的行为)用对象的操作表示。
一个对象通常可由对象名、属性和方法 3 个部分组成。
# 消息
对象之间进行通信的一种构造叫作消息。当一个消息发送给某个对象时,包含要求接收对象去执行某些活动的信息。接收到信息的对象经过解释,然后予以响应。这种通信机制称为消息传递。发送消息的对象不需要知道接收消息的对象如何对请求予以响应。
# 类
类就是对事物进行分类,把具有相同属性和相同操作的对象归为一类,类是这些对象的抽象描述,每个对象是它的类的一个实例(类的实例称为对象)。
一个类定义了一组大体上相似的对象。一个类所包含的方法和数据描述一组对象的共同行为和属性。
类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。
类可以分为三种:
- 实体类:实体类的对象表示现实世界中真实的实体。
- 接口类:接口类(边界类)的对象为用户提供一种与系统合作交互的方式。
- 控制类:控制类的对象用来控制活动流,充当协调者。
# 面向对象三大特性
子类 = 派生类 = 特殊类
父类 = 基类 = 超类 = 祖先类 = 一般类
重写 = 覆写 = 覆盖 = 置换
# 封装
封装是一种信息隐蔽技术,它的目的是使对象的使用者和生产者分离,使对象的定义和实现分开。
封装是将数据和操作封装为一个整体,由于类中私有成员都是隐藏的,只向外部提供有限的接口,所以能够保证内部的高内聚性和与外部的低耦合性。用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员,能够增强安全性和简化编程。
封装就是把抽象出来的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作。
# 继承
通过在不同程度上运用抽象的原则(较多或较少地忽略事物之间的差异),可以得到较一般的类(父类)和较特殊的类(子类)。特殊类(子类)继承一般类(父类)的属性和操作。
继承是父类和子类之间共享数据和方法的机制。这是类之间的一种关系,在定义和实现一个类的时候,可以在一个已经存在的类的基础上进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。
一个父类可以有多个子类,这些子类都是父类的特例,父类描述了这些子类的公共属性和方法。一个子类可以继承它的父类中的属性和方法,这些属性和操作在子类中不必定义,子类中还可以定义自己的属性和方法。
如果一个子类只从一个父类得到继承,叫作“单重继承”。如果从多个父类得到继承,则称为“多重继承”。
# 多态
多态性是指同一操作作用于不同对象,可以有不同的解释,产生不同的执行结果。
在收到消息时,对象要予以响应。不同的对象收到同一消息可以产生完全不同的结果,这一现象称为多态。在使用多态的时候,用户可以发送一个通用的消息,而实现的细节则由接收对象自行决定。这样,同一消息就可以调用不同的方法。
多态的实现受到继承的支持,利用类的继承的层次关系,把具有通用功能的消息存放在高层次,而不同的实现这一功能的行为放在较低层次,在这些低层次上生成的对象能够给通用消息以不同的响应。
多态的不同形式:
- 通用多态
- 参数多态:应用比较广泛的多态,被称为最纯的多态。采用参数化模板,通过给出不同的类型参数,使得一个结构有多种类型。
- 包含多态:包含多态在许多语言中存在,最常见的例子就是子类型化,即一个类型是另一个类型的子类型。
- 特定多态
- 过载多态:过载多态是同一个名字(操作符﹑函数名)在不同的上下文所代表的含义不同。
- 强制多态:编译程序通过语义操作,把操作对象的类型强行加以变换,以符合函数或操作符的要求。在发生不同类型的数据进行混合运算时,编译程序一般都会进行强制多态。
# 面向对象三个步骤
你要建个网上商城,那就首先要把客观的业务需求转化为各个功能模块,用户、菜单(登录菜单、购物菜单、商品菜单、其他菜单)、商品管理员等,这个过程就是 OOA;根据上面的理论模型制定实现方案,将模型映射为具体的对象,这个就是 OOD 过程;最后按照设计代码实现的过程就是 OOP。
# 面向对象分析
面向对象分析(OOA)的实质就是建模,对客观存在的事物建立理论模型。
- 认定对象
- 组织对象
- 描述对象间的相互作用
- 确定对象的操作
- 定义对象的内部信息
# 面向对象设计
面向对象设计(OOD)实际上就是把分析阶段得到的需求抽象为系统实现方案的过程。
- 识别类及对象
- 定义属性
- 定义服务
- 识别关系
- 识别包
# 面向对象编程
面向对象编程(OOP)即把设计好的系统通过代码编程实现。
# 面向对象设计原则
# 五大设计原则
单一责任原则(SRP):就一个类而言,应该仅有一个引起它变化的原因。即,当需要修改某个类的时候原因有且只有一个,让一个类只做一种类型责任。
开放-封闭原则(OCP):软件实体(类、模块、函数等)应该是可以扩展的(开放的),但是不可修改的(封闭的)。
里氏替换原则(LSP):子类型必须能够替换掉他们的基类型。即,在任何父类可以出现的地方,都可以用子类的实例来赋值给父类型的引用。当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有是一个(is-a)关系。
接口分离原则(ISP):不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。即,依赖于抽象,不要依赖于具体,同时在抽象级别不应该有对于细节的依赖。这样做的好处就在于可以最大限度地应对可能的变化。
依赖倒置原则(DIP):抽象不应该依赖于细节,细节应该依赖于抽象。即,高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
# 其他设计原则
重用发布等价原则(REP):重用的粒度就是发布的粒度。
共同封闭原则(CCP):包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包产生影响,则将对该包中的所有类产生影响,而对于其他的包不造成任何影响。
共同重用原则(CRP):一个包中的所有类应该是共同重用的。如果重用了包中的一个类,那么就要重用包中的所有类。
无环依赖原则(ADP):在包的依赖关系图中不允许存在环,即包之间的结构必须是一个直接的五环图形。
稳定依赖原则(SDP):朝着稳定的方向进行依赖。
稳定抽象原则(SAP):包的抽象程度应该和其稳定程度一致。
# 面向对象杂题选讲
https://www.bilibili.com/video/BV1QU4y1o7MS?p=75 (opens new window)