当前位置:   article > 正文

[架构之路-136]-《软考-系统架构设计师》-软件工程-6-软件系统设计-23种设计模式(面向对象的可复用设计)_设计模式-可复用软件的设计

设计模式-可复用软件的设计

第1章 二十三种设计模式概述

1.1 概述

设计模式(Design pattern) 是解决软件开发某些特定问题而提出的一些解决方案,也可以理解成解决问题的一些思路。通过设计模式可以帮助我们增强代码的可重用性、可扩充性、 可维护性、灵活性好。我们使用设计模式最终的目的是实现代码的高内聚和低耦合。

创建性模式(新团队成员):如何创建一组相互关联的对象。

结构性模式(组织架构):如何把多个对象组成成一个更大的组织静态架构。

行为性模式(行为流程):如何定义多个对象之间的行为方式,确保完成某种特定的职责。

设计模式是探讨如何有效的组织大量的对象!!!

以完成某种特定的功能!!!

这与组件团队和运营公司是相似的!!!

每个对象,相当于一个人,把一个对象组成一个更大的对象,相当于组件一个更大的团队。

定义对象之间的职责分工和行为方式,相当于定义团队的职责与对外交互流程。

因此,一个软件系统,其实就是一个公司,运营一个软件系统,与运营一个公司是相似的。

当然,软件系统是完成某个特定的业务,因此,严格意义上讲,一个软件系统,实际上是公司运营的一个侧面,一个视图,而不是全部。

只有把公司、业务、软件这三者关联起来,才能更加形象地理解设计模式在设计软件项目中应用,因为,软件项目是为业务服务的,是软件化、数字化后的业务模式!!!

看抽象的设计模式,如果能够与运营公司连续起来,设计模式就不再抽象了。

1.2 设计模式与设计原则的关系

  • 单一职责原则:要求在软件系统中,一个类只负责一个功能领域中的相应职责。

  • 开闭原则:要求一个软件实体应当对扩展开放,对修改关闭,即在不修改原先已有代码的基础上扩展一个系统的行为。

  • 里氏替换原则:可以通俗表述为在软件中如果能使用基类对象,那么一定能够使用其子类对象。这是因为子类对象内存空间比父类对象的内存空间大,且子类继承下来的父类与原先的父类具有相同的结构体和内存空间分布

  • 依赖倒置原则:要求抽象不应该依赖于细节,细节应该依赖于抽象;要针对接口编程,不要针对实现编程。 之所以称为倒置,是因为在软件层次上,抽象在下层,具体实现在上层。

  • 接口隔禽原则:要求客户端不应该依赖那些它不需要的接口,即将一些大的接口细化成一些小的接口供客户端使用。使用单一功能的接口比功能丰富的接口要好。

  • 合成复用原则:要求复用时尽量使用对象組合,而不使用继承。继承导致子类与父类是强依赖关系,不符合低耦合的原则!

  • 迪米特法则:要求一个软件实体应当尽可能少的与其他实体发生相互作用。

第2章 创建性模式:HR招聘新团队和公司组件新团队的几种模式

问题:为什么不直接用new来创建对象,而需要通过设计模式来创建对象???

原因:

  • 用new创建对象,需要创建者后期维护和管理对象,new本身无法胜任。

  • 一个对象,除了创建,还需要初始化,new无法完成复杂的初始化工作。

  • 创建一个对象,还有一些列的依赖关系的对象,new本身无法实现。

因此,需要有一种机制,它能够自动创建和初始对象,解决对象之间的各种依赖关系。使用者只需要通过它就可以获得完整的创建好的对象!!!正所谓,社会分工,有些人专门做“生成对象”的任务。

  • 单例模式:某个类只能有一个实例,别无选择,提供一个全局访问点

  • 原型模式:通过复制现有的实例来创建新的实例

新对象是由一个对象克隆而来

  • 工厂模式:一个工厂类根据传入的参量决定创建出哪一种产品类的实例。

定义一个用于创建对象的接口,让子类决定实例化哪一个类。

Factory Method 使一个类的实例化延迟到其子类。

  • 抽象工厂模式:创建相关或依赖对象的家族,而无需明确指定具体类

  • 建造者模式:封装一个复杂对象的创建过程,并可以按步骤构造

由builder分步骤、分阶段构建多个对象。

第3章 结构性模式(组织架构)

把类或对象结合在一起形成一个更大的结构。

  • 装饰器模式:动态的给对象添加新的功能。

  • Proxy代理模式:其它对象提供一个代理以便控制这个对象的访问, 代理负责内外的转换!

  • 桥接模式:抽象部分和它的实现部分分离,使它们都可以各自独立的变化

  • 适配器模式:将一个类的方法接口转换成客户希望的另一个接口

将一个类的接口转换成客户希望的另外一个接口。

Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

  • 组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。

将对象组合成树形结构以表示“部分-整体”的层次结构。

C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。

用组合替代继承,是面向对象推荐的方法。

  • 外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。

  • 享元模式:通过共享技术来有效的支持大量细粒度的对象。

一个应用程序使用了大量的对象。

完全由于使用大量的对象,造成很大的存储开销。

对象的内部大多数状态都可变为外部共享状态

如果删除对象的内部状态,那么可以用相对较少的共享对象取代很多组对象内部状态

应用程序不依赖于对象标识

由于Flyweight 对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

Flyweight 对象为多个对象共享!!!它的职责就是为多个对象提供共享内存!!!

第4章 行为型模式

类和对象如何交互,及划分责任和算法。

  • Strategy策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。

本模式使得算法可独立于使用它的客户而变化

意图:

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

适用性:

许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。

需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[H087] ,可以使用策略模式。

算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。

一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

  • 模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。

TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是Opdyke 和Johnson 所描述过的“重分解以一般化”的一个很好的例子[ OJ93 ]。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。

控制子类扩展。模板方法只在特定点调用“hook ”操作(参见效果一节),这样就只允许在这些点进行扩展。

  • command命令模式:命令请求封装为一个对象,使得可以用不同的请求来进行参数化。

对请求排队或记录请求日志,以及支持可撤消的操作。

  • Iterator迭代器模式:一种遍历访问聚合对象中各个元素的方法不暴露该对象的内部结构

访问一个聚合对象的内容而无需暴露它的内部表示。

支持对聚合对象的多种遍历。

为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

  • 观察者模式:对象间的一对多的依赖关系。

定义对象间的一种一对多依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。

当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。

当一个对象必须通知其它对象,而它又不能假定其它对象是谁。

换言之, 你不希望这些对象是紧密耦合的。

  • Mediator中介者模式:用一个中介对象来连接一系列的对象交互,由点对点通信转化成星形通信模式,这发生在对等的对象间通信或上下层对象间通信。

用一个中介对象来封装一系列的对象之间的交互。

中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

适用性:

一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。

一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。

想定制一个分布在多个类中的行为,而又不想生成太多的子类。

  • Memento备忘录模式:在不破坏封装的前提下,保持对象的内部状态。

通过GetState获取状态,通过SetState设置状态。

意图:

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

这样以后就可将该对象恢复到原先保存的状态。

适用性:

必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。

如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。

  • Interpreter解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器

意图:

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

适用性:

当有一个语言需要解释后执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:

该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。

效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。

  • State状态模式:允许一个对象在其对象内部状态改变时改变它的行为

意图:

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

通过stateHandle,在状态改变时,实现其行为的改变。

适用性:

一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。

一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

  • Chain of Responsibility责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。

意图:

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

适用性:

有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。

你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

可处理一个请求的对象集合应被动态指定。

  • Visitor访问者模式:不改变数据结构的前提下,增加作用于一组对象元素的新功能。

意图:

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

适用性:

一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是Opdyke和Johnson所描述过的“重分解以一般化”的一个很好的例子[OJ93]。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。

控制子类扩展。模板方法只在特定点调用“hook ”操作(参见效果一节),这样就只允许在这些点进行扩展。

第5章 各种设计模式的关系

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/213325
推荐阅读
相关标签
  

闽ICP备14008679号