放弃不难,但坚持一定很酷!
一、面向对象基础
(一)基本概念
对象
:对象是基本的运行时的实体,既包括数据(属性),也包括作用于数据的操作(行为)。一个对象把属性和行为封装成一个整体消息
:对象之间进行通信的一种构造叫作消息类
:一个类所包含的方法和数据描述一组对象的共同行为和属性。类是在对象之上的抽象,对象是类的具体化,是类的实例。类分为三种
- 实体类
- 接口类(边界类)
- 控制类
封装
:一种信息隐蔽技术,使对象的使用者和生产者分离,使对象的定义和实现分开继承
:继承是父类和子类之间共享数据和方法的机制。子类从一个父类得到继承,叫作“单重继承”;一个子类有两个或多个父类,叫作“多重继承”多态
:不同对象收到同一消息产生完全不同的结果(重载+重写+类属)
- 通用的多态:参数多态和包含多态
- 特定的多态:过载多态和强制多态
绑定
:把过程调用和响应调用所需要执行的代码加以结合的过程。一般情况下,绑定是在编译时进行的,叫作静态绑定,而动态绑定是在运行时进行的动态绑定
:当一个对象发送消息请求服务时,根据接受对象的具体情况将请求的操作与实现的方法进行连接面向对象分析(OOA)
:包含5个活动
- 认定对象
- 组织对象
- 描述对象间的相互作用
- 确定对象的操作
- 定义对象的内部信息
面向对象设计(OOD)
:与OOA对应如下5个活动
- 识别类及对象
- 定义属性
- 定义服务
- 识别关系
- 识别包
(二)设计原则
单一职责原则
:设计目的单一的类开放—封闭原则
:对扩展开放,对修改封闭(多扩展,少修改)里氏替换原则
:子类可以替换父类依赖倒置原则
:要依赖于抽象,而不是具体实现;针对接口编程,不要针对实现编程接口分离原则
:使用多个专门的接口比使用单一的总接口要好组合重用原则
:要尽量使用组合,而不是继承关系达到重用的目的迪米特原则
(最少知识法则):一个对象应当对其他对象有尽可能少的了解面向对象测试
:面向对象的综合测试是由底向上的测试。可分以下4个层次
- 算法层
- 类层
- 模板层
- 系统层
二、UML(统一建模语言)
事务
- 结构事务:UML中的名词,包括类、接口、协作、用例、主动类、构件、制品和结点
- 行为事务:UML中的动态部分,包括交互、状态机和活动
- 分组事务:UML中的组织部分,最重要的是包
- 注释事务:UML中的解释部分,用来描述、说明和标注模型的任何元素
关系
- 依赖:依赖是两个事物间的语义关系,其中一个事物(独立事物)发生变化会影响另一个事物(依赖事物)的语义。在图形上,把一个依赖画成一条可能有方向的虚线
- 关联:关联是一种结构关系,它描述了一组链,链是对象之间的连接。聚合是一种特殊类型的关联,它描述了整体和部分间的结构关系。组合也是一种特殊类型的关联,它同样体现了整体与部分间的关系,但比聚合更强,也称为强聚合
- 泛化:泛化是一种特殊/一般关系,特殊元素(子元素)的对象可替代一般元素(父元素)的对象。用这种方法,子元素共享了父元素的结构和行为。在图形上,把泛化关系画成一条带有空心箭头的实线,它指向父元素
- 实现:实现是类元之间的语义关系,其中一个类元指定了由另一个类元保证执行的契约。在两种情况下会使用实现关系:一种是在接口和实现它们的类或构件之间,另一种是在用例和实现它们的协作之间。在图形上,把一个实现关系画成一条带有空心箭头的虚线
图
:一组元素的图形表示,大多数情况下把图画成顶点(代表事物)和弧(代表关系)的连通图
- 结构图(静态图)
- 类图:类图展现了一组对象、接口、协作和它们之间的关系。类图给出系统的静态设计视图
- 对象图:对象图展现了某一时刻一组对象以及它们之间的关系,描述了在类图中所建立的事物的实例的静态快照。对象图给出系统的静态视图或静态进程视图
- 包图:包图是用于把模型本身组织成层次结构的通用机制,不能执行,展现由模型本身分解而成的组织单元以及其间的依赖关系
- 组合构件图:组合结构图用于描述一个分类器(如类、构件或用例)的内部结构,展示一组相互协作的实例如何完成特定的任务,描述设计、架构模式或策略
- 构件图:构件图展现了一组构件之间的组织和依赖。专注于系统的静态实现视图。它与类图相关,通常把构件映射为一个或多个类、接口或协作
- 部署图:部署图是用来对面向对象系统的物理方面建模的方法,展现了运行时处理结点以及其中构件(制品)的配置。对系统的静态部署视图进行建模,与构件图相关
- 行为图(动态图)
- 用例图:用例图展现了一组用例、参与者以及它们之间的关系。对系统的静态用例视图进行建模
- 交互图–顺序图(序列图):序列图是场景的图形化表示,描述了以时间顺序组织的对象之间的交互活动
- 交互图–通信图(协作图):通信图强调收发消息的对象的结构组织,强调参加交互的对象的组织
- 定时图(计时图):定时图是另一种新增的、特别适合实时和嵌入式系统建模的交互图,关注沿着线性时间轴、生命线内部和生命线之间的条件改变
- 状态图:状态图展现了一个状态机,它由状态、转换、事件和活动组成。关注于系统的动态视图,对于接口、类和协作的行为建模尤为重要,强调对象行为的时间顺序
- 活动图:活动图是一种特殊的状态图,它展现了在系统内从一个活动到另一个活动的流程。专注于系统的动态视图,强调对象间的控制流程
- 交互概览图:交互概览图是UML2.0新增的交互图之一,它是活动图的变体,描述业务过程中的控制流概览,软件过程中的详细逻辑概览,以及将多个图进行连接,抽象掉了消息和生命线,其中的活动也都是交互发生
三、设计模式
(一)概念与分类
(二)创建型模式
工厂方法模式(Factory Method )
- 意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。使一个类的实例化延迟到其子类
- 适用性:
- 当一个类不知道它所必须创建的对象的类的时候
- 当一个类希望由它的子类来指定它所创建的对象的时候
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
抽象工厂模式(Abstract Factory)
- 意图:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类
- 适用性:
- 一个系统要独立于它的产品的创建、组合和表示时
- 一个系统要由多个产品系列中的一个来配置时
- 当要强调一系列相关的产品对象的设计以便进行联合使用时
- 当提供一个产品类库,只想显示它们的接口而不是实现时
原型模式(Prototype)
- 意图:用原型实例指定创建对象的种类,并且通过复制这些原型来创建新的对象
- 适用性:
- 当一个系统应该独立于它的产品创建、构成和表示时
- 当要实例化的类是在运行时被指定时
- 为了避免创建一个与产品类层次平行的工厂类层次时
- 当一个类的实例只能有几个不同状态组合中的一种时
单例模式(Singleton)
- 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点
- 适用性:
- 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时
- 当这个唯一实例应该是通过子类化可扩展的,并且客户无须更改代码就能使用一个扩展的实例时
构建器模式(Builder)
- 意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
- 适用性:
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时
- 当构造过程必须允许被构造的对象有不同的表示时
(三)结构型模式
适配器模式(Adapter)
- 意图:将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
- 适用性:
- 想使用一个已存在的类,而它的接口不符合要求
- 想创建一个可以服用的类,该类可以与其他不相关的类或不可预见的类(接口不兼容的类)协同工作
- 想使用一个已存在的类,但是不可能对每一个都进行子类化以匹配它们的接口
桥接模式(Bridge)
- 意图:将抽象部分与其实现部分分离,使它们可以独立地变化
- 适用性:
- 不希望在抽象和它的实现部分之间有一个固定的绑定关系
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以补充
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译
- 想对客户完全隐藏抽象的实现部分
- 有许多类要生成的类层次结构
- 想在多个对象间共享实现,但同时要求客户并不知道这一点
组合模式(Composite)
- 意图:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性
- 适用性:
- 想表示对象的部分-整体层次结构
- 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
装饰模式(Decorator)
- 意图:动态地给一个对象添加一些额外的职责
- 适用性:
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
- 处理那些可以撤销的职责
- 当不能采用生成子类的方式进行扩充时
外观模式(Facade)
- 意图:为子系统中的一组接口提供一个一致的界面。定义了一个高层接口,这个接口使得这一子系统更加容易使用
- 适用性:
- 要为一个复杂子系统提供一个简单接口时,子系统往往因为不断演化而变得越来越复杂
- 客户程序与抽象类的实现部分之间存在着很大的依赖性
- 当需要构建一个层次结构的子系统时,使用Facade模式当以子系统中每层的入口点
享元模式(Flyweight)
- 意图:运用共享技术有效地支持打两细粒度的对象
- 适用性:
- 一个应用程序使用了大量的对象
- 完全由于使用大量的对象,造成很大的存储开销
- 对象的大多数状态都可以变为外部状态
- 若删除对象的外部状态,则可以用相对较少的共享对象取代很多组对象
- 应用程序不依赖于对象标识
代理模式(Proxy)
- 意图:为其他对象提供一种代理以控制对这个对象的访问
- 适用性*:
Proxy模式适用于在需要比较通用和复杂的对象指针代替简单的指针时,常见情况:
- 远程代理为一个对象在不同地址空间提供局部代表
- 虚代理根据需要创建开销很大的对象
- 保护代理控制对原始对象的访问,用于对象应该有不同访问权限的时候
- 智能引用取代了简单指针,在访问对象时执行一些附加操作
(四)行为型模式
责任链模式(Chain of Responsibility)
- 意图:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
- 适用性:
- 有多个对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定
- 想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
- 可处理一个请求的对象集合应被动态指定
命令模式(Command)
- 意图:将请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
- 适用性:
- 抽象出待执行的动作以参数化某对象
- 在不同的时刻指定、排列和执行请求
- 支持取消操作
- 支持修改日志
- 用构建在原语操作上的高层操作构造一个系统
解释器模式(Interpreter)
- 意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
- 适用性:
- 该文法简单
- 效率不是一个关键问题
迭代器模式(Iterator)
- 意图:提供一种方法顺序访问一个聚合对象中的各个元素,且不需要暴露该对象的内部表示
- 适用性:
- 访问一个聚合对象的内容而无须暴露它的内部表示
- 支持对聚合对象的多种遍历
- 为遍历不同的聚合结构提供一个统一的接口
中介者模式(Mediator)
- 意图:用一个中介对象来封装一系列的对象交互。使各对象不需要显式地相互引用,从而使耦合松散,而且可以独立地改变它们之间的交互
- 适用性:
- 一组对象以定义良好但是复杂的方式进行通信,产生的相互依赖关系结构混乱且难以理解
- 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象
- 想定制一个分布在多个类中的行为,而又不想生成太多的子类
备忘录模式(Memento)
- 意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态
- 适用性:
- 必须保存一个对象在某一时刻的状态,这样以后需要时它才能恢复到先前的状态
- 如果一个用接口来让其他对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性
观察者模式(Observer)
- 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都能得到通知,并被自动更新
- 适用性:
- 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立地改变和复用
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变时
- 当一个对象必须通知其他对象,而它又不能假定其他对象是谁,即不希望这些对象是紧耦合的
状态模式(State)
- 意图:允许一个对象在其内部状态改变时改变它的行为
- 适用性:
- 一个对象的行为决定于它的状态,并且它必须在运行时根据状态改变它的行为
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态
策略模式(Strategy)
- 意图:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换
- 适用性:
- 许多相关的类仅仅是行为有异
- 需要使用一个算法的不同变体
- 算法使用客户不应该知道的数据
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,将相关的条件分支移入它们各自的Strategy类中,以代替这些条件语句
模板方法模式(Template Method)
- 意图:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
- 适用性:
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现
- 各子类中公共的行为应被提取出来,并集中到一个公共父类中,以避免代码重复控制子类扩展
访问者模式(Visitor)
- 意图:标识一个作用于某对象结构中的各元素的操作,它允许在不改变各元素的类的前提下定义作用于这些元素的新操作
- 适用性:
- 一个对象结构包含很多类对象,它们有不同的接口,而用户想对这些对象实施一些依赖于其具体类的操作
- 需要对一个对象结构中的对象进行很多不同的、不相关的操作,又想避免这些操作“污染”这些对象的类
- 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作