1.什么是设计模式?
- “每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。 ——Christopher Alexander
-
从面向对象谈起
1.1底层思维与抽象思维
- 底层思维:向下,如何把握机器底层从微观理解对象构造
- 语言构造
- 编译转换
- 内存模型
- 运行时机制
- 抽象思维:向上,如何将我们的周围世界抽象为程序代码
- 面向对象
- 组件封装
- 设计模式
- 架构模式
1.2深入理解面对对象
- 向下:深入理解三大面向对象机制
- 封装,隐藏内部实现
- 继承,复用现有代码
- 多态,改写对象行为
- 向上:深刻把握面向对象机制所带来的抽象意义,理解如何使用这些机制来表达现实世界,掌握什么是“好的面向对象设计”
1.3如何解决复杂性?
1. 分解
- 人们面对复杂性有一个常见的做法:即分而治之,将大问题分解为多个小问题,将复杂问题分解为多个简单问题
2. 抽象
- • 更高层次来讲,人们处理复杂性有一个通用的技术,即抽象。由于不能掌握全部的复杂对象,我们选择忽视它的非本质细节,而去处理泛化和理想化了的对象模型。
1.4软件设计的目标
- 复用!
1.5为何使用面向对象设计?
- 变化是复用的天敌!面向对象设计最大的优势在于:抵御变化!
1.6重新认识面向对象
- 理解隔离变化
- 从宏观层面来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小
- 各司其职
- 从微观层面来看,面向对象的方式更强调各个类的"责任"
- 由于需求变化导致的新增类型不应该影响原来类型的实现——即各司其责
- 对象是什么?
- 从语言实现层面来看,对象封装了代码和数据
- 从规格层面讲,对象是一系列可被使用的公共接口
- 从概念层面讲,对象是某种拥有责任的抽象
2.设计模式七大原则
3. 模式分类
3.1从目的分类
- 创建型(Creational)模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离(或延迟)”
- 5种: 单例、原型、工厂方法、抽象工厂、建造者
- 结构型(Structural)模式:用于描述如何将类或对象按某种布局组成更大的结构
- 7种: 代理、适配器、桥接、装饰、外观、享元、组合
- 行为型(Behavioral)模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责
- 11种: 模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器
3.2从范围分类
- 类模式处理类与子类的静态关系。
- 对象模式处理对象间的动态关系。
3.3从封装变化角度分类
- “组件协作”模式:
- 现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式
- 典型模式:
- 模板(方法)模式 Template Method
- 观察者 Observer / Event
- 策略 Strategy
- "对象性能"模式:
- 面向对象很好地解决了"抽象"的问题,但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。
- 典型模式:
- 单例 Singleton
- 享元 Flyweight
- "单一职责"模式:
- 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。
- 典型模式:
- 装饰者 Decorator
- 桥接 Bridge
- "对象创建"模式:
- 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。
- 典型模式:
- 工厂方法 Factory Method
- 抽象工厂 Abstract Factory
- 原型 Prototype
- 建造者 Builder
- "接口隔离"模式:
- 在组件构建过程中,某些接口之间直接的依赖常常会带来很多问题、甚至根本无法实现。采用添加一层间接(稳定)接口,来隔离本来互相紧密关联的接口是一种常见的解决方案。
- 典型模式:
- 外观 Facade
- 代理 Proxy
- 适配器 Adapter
- 中介 Mediator
- “数据结构”模式:
- 常常有一些组件在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。这时候,将这些特定数据结构封装在内部,在外部提供统一的接口 , 来实现与特定数据结构无关的访问,是一种行之有效的解决方案。
- 典型模式:
- 组合 Composite
- 迭代器 Iterator
- 责任链Chain of Resposibility
- “状态变化” 模式:
- 在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一问题提供了一种解决方案。
- 典型模式:
- 状态 State
- 备忘录 Memento
- “行为变化”模式:
- 在组件的构建过程中,组件行为的变化经常导致组件本身剧烈的变化。”行为变化” 模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现两者之间的松耦合。
- 典型模式:
- 命令 Command
- 访问者 Visitor
- “领域规则” 模式:
- 在特定领域中,某些变化虽然频繁,但可以抽象为某种规则。这时候,结合特定领域,将问题抽象为语法规则,从而给出在该领域下的一般性解决方案。
- 典型模式:
- 解释器 Interpreter
4.小结
4.1重构获得模式 (Refactoring to Patterns)
1. 面向对象设计模式是“好的面向对象设计”,所谓“好的面向对象设计”指是那些可以满足 “应对变化,提高复用”的设计 。
1. 现代软件设计的特征是“需求的频繁变化”。设计模式的要点是“寻找变化点,然后在变化点处应用设计模式,从而来更好地应对需求的变化”.“什么时候、什么地点应用设计模式”比“理解设计模式结构本身”更为重要。
1. 设计模式的应用不宜先入为主,一上来就使用设计模式是对设计模式的最大误用。没有一步到位的设计模式。敏捷软件开发实践提倡的“Refactoring to Patterns”是目前普遍公认的最好的使用设计模式的方法。
1. 重构关键技法
- 静态 --> 动态
- 早绑定 --> 晚绑定
- 继承 --> 组合
- 编译时依赖 --> 运行时依赖
- 紧耦合 --> 松耦合
4.2将设计原则提升为设计经验
1. 设计习语 Design Idioms
- Design Idioms 描述与特定编程语言相关的低层模式,技巧,惯用法。
2. 设计模式 Design Patterns
- Design Patterns主要描述的是“类与相互通信的对象之间的组织关系,包括它们的角色、职责、协作方式等方面
3. 架构模式 Architectural Patterns
- Architectural Patterns描述系统中与基本结构组织关系密切的高层模式,包括子系统划分,职责,以及如何组织它们之间关系的规则。
5.设计模式总结
一个目标
- 管理变化, 提高复用
两种手段
- 分解
- 抽象
七大原则
关注稳定点和变化点
- 
什么时候不用模式?
1. 代码可读性很差时
1. 需求理解还很浅时
1. 变化没有显现时
1. 不是系统的关键依赖点
1. 项目没有复用价值时
1. 项目将要发布时
经验之谈
1. **不要为模式而模式**
1. 关注抽象类&接口
1. 理清变化点和稳定点
1. 审视依赖关系
1. 要有Framework和Application的区隔思维
1. 良好的设计是演化的结果
设计模式成长之路
1. “手中无剑,心中无剑”: 见模式而不知
1. “手中有剑心中无剑”: 可以识别模式,作为应用开发人员**使用**模式
1. “手中有剑,心中有剑”: 作为框架开发人员为应用**设计**某些模式
1. “手中无剑,心中有剑”: **忘掉模式,只有原则**
6.代码规范
- 低耦合:
- 缓冲层
- 单一职责:
- 多对象化
- 拒绝长函数:
- 分解为多个子函数
- 标识符:
- 描述性命名, 动词命方法名.
- 代码的自描述性. 形成自己的风格
- 幻术/魔法值: 避免
- 深度嵌套: 避免.
- 3-4层 循环/switch/if-else 即可使用状态机/测略模式, 抽离不变的代码
- 注释:
- 类, 方法, 算法. 解释代码块存在目的, 而非解释其在做什么
- 不能自解释的部分, 一定注释.
- 避免过渡注释/注释与代码脱节/注释混淆代码
- 工具类/方法:
- static化
- 编码准备:
- 结构图/时序图
- <br />
x.其它: 学习资料
x.1 23个设计模式(C++)
23个设计模式-李建忠(C++代码讲解, 较宏观抽象)
配套课件与源码
x.2 尚硅谷-韩顺平: 图解Java设计模式
尚硅谷韩顺平图解Java设计模式.pdf
尚硅谷韩顺平图解Java设计模式.pdf