本文主要内容来自 SpriCoder的博客,更换了更清晰的图片并对原文的疏漏做了补充和修正。
可修改性及其基本实现机制
- 实现的可修改性:涉及到大的场景的修改
- 对已有实现的修改
- 例如:修改现有促销策略
- 实现的可扩展性(DIP & OCP)
- 对新的实现的扩展
- 例如:增加一条新的促销策略(策略模式)
- 实现的灵活性
- 对实现的动态配置
- 例如:动态修改更改某商品对应促销策略
如何实现可修改性? 重要
- 接口与实现的分离
如何将接口与实现的分离 -- Java 视角
- 通过接口与实现该接口的类,将接口与实现相分离
- 通过子类继承父类,将父类的接口与子类的实现相分离:通过继承的方式,在一定程度上实现了接口与实现的分离,但是也使得子类继承了父类的接口,使得灵活性略有下降。
- Eg.课本 263 页
实现接口(interface)
- interface:定义了规约
- 实现 class:实现了规约
类图中的标志物的含义
- 虚线箭头:依赖
- 实线箭头:关联(两侧写数量)
- 空菱形在一侧的实现箭头:聚合
- 实菱形在一侧的实现箭头:合成
- 空心实线箭头:泛化(extends)
- 空心虚线箭头:实现(implements)
类图与依赖关系
- Client、Interface_A、Class_A1 之间是什么关系?
- Client 和 Class_A1 是否存在依赖关系?
继承
- 父类定义了规约(contract)
- 子类实现了规约(contract)
类图与依赖关系
- Client、Super_A、Sub_A1 之间是什么关系?
- Client 和 Sub_A1 是否存在依赖关系?不
实现的可修改性
- 对于实现的可修改性,无论是 Class_A1 还是 Sub_A1 的 method_A 方法的实现的修改都和 Client 中的调用代码没有任何耦合性。
扩展
实现的可扩展性
- 对于实现的可扩展性,我们可以通过 Class_A2 还是 Sub_A2 的创建来实现。
实现的灵活性
继承的优点
- 虽然继承也能很好的完成接口与实现的分离,但是继承还有他独有的特征。
- 子类不但继承了父类的接口还继承了父类的实现,这可以更好的进行代码的重用。
继承的缺点
- 继承的父类与所有子类存在共有接口的耦合性。当父类接口发生改变的时候,子类的接口就一定会更改,这样就会影响到 Client 代码。
- 而且当子类创建对象的时候,就决定了其实现的选择,没法再动态的修改。
组合
- 而利用接口的组成关系,却能在实现接口和实现的前提下,体现更好的灵活性。前端类和后端类是组合关系。前段类重用了后端类的代码。
- 考虑到软件工程中的人的重要性。
组合的优点
- 前端和后端在接口上不存在耦合性。当后端接口发送改变的时候,并不会直接影响到 Client 代码。
- 后端类的实现亦可以动态创建、动态配置、动态销毁,非常灵活。
设计模式
Why?为什么使用设计模式
- 设计 OO 软件非常困难
- 设计可重用的 OO 软件-难度更大
- 经验丰富的 OO 设计师可以做出出色的设计
- 新设计师倾向于使用以前使用的非 OO 技术
- 经验丰富的设计师知道一些东西-这是什么?
- 专家设计师知道不能从第一原则中解决所有问题
- 复用的解决方案
- 这些模式使面向对象的设计更加灵活,优雅并且最终可重用。
什么是设计模式
- 设计模式:抽象一个重复的设计结构
- 包含类和/或对象
- 依赖
- 结构
- 互动,或
- 约定
- 提炼设计经验
模式
- 典型问题
- 设计分析
- 解决方案
- 案例
解决方案
- 组成与协作:描述了设计中涉及的各个类的组成成分,他们之间的相互关系及各自的职责和协作方式。
- 应用场景:描述了应该何时使用模式。它解释了设计模式所要解决的问题,以及解决这个问题时所面临的特点的环境、限制条件、场景等。这也是我们在应用某种模式之前,需要仔细去体察的。
- 使用注意点:因为模式只是一个模板,他可以应用与多种不同场合,所以解决方案并不描述一个具体的实现,而是提供解决方案的一个抽象模型。
设计模式和策略配对
- 策略模式:减少耦合、依赖倒置。
- 抽象工厂模式:职责抽象、接口重用。
- 单件模式:信息隐藏、职责抽象。
- 迭代器模式:减少耦合、依赖倒置。
设计模式重点掌握类图重要
- 策略模式
- 抽象工厂模式
- 单件模式
- 迭代器模式
题目
- 给定场景,利用设计模式写出代码
- 给出代码,利用设计模式重写
- 设计模式内容具体查看