GeekBand C++设计模式 第一周

1.设计模式简介

课程目标

  • 松耦合设计思想
  • 面向对象设计原则
  • 重构技法改善设计
  • GOF核心设计模式

设计模式

  • 不断重复发生的问题
  • 解决方案的核心
  • 重复使用

面向对象:

  • 向下,如何把握机器底层从微观理解对象构造
    • 语言构造
    • 编译转换
    • 内存模型
    • 运行时机制
  • 向上:如何将我们周围的世界抽象为程序代码
  • 面向对象
  • 组件封装
  • 设计模式
  • 架构模式

深入理解面向对象:

  • 向下:三大面向对象机制
    • 封装,隐藏内部实现
    • 继承,复用现有代码
    • 多态,改写对象行为
  • 向上:深刻把握面向对象机制所带来的抽象意义,理解如何使用这些机制来表达现实世界,掌握什么是“好的面向对象设计”

软件设计复杂的根本原因:变化

  • 客户需求
  • 技术平台
  • 开发团队
  • 市场环境
  • ...

解决问题的思维模型:

  • 分解:将大问题分解为多个小问题,将复杂问题分解为多个简单的问题(C语言为代表)
  • 抽象:由于不能掌握全部的复杂对象,我们选择忽视它的非本质细节而去处理泛化和理想化了的对象模型
什么是好的软件设计?软件设计的金科玉律:复用!

2.面向对象设计原则

变化是复用的天敌!面向对象设计最大的优势在于:抵御变化!

重新认识面向对象:

  • 隔离变化:能将变化所带来的影响减到最小。
  • 各司其职:面向对象的方式强调个各类的“职责”,新增加的类不会影响原有类。
  • 对象是什么?
    • 语言:对象封装了代码和数据。
    • 规格:对象是一系列可被使用的公共接口。
    • 概念:对象是某种拥有责任的抽象。

面向对象设计原则:

设计原则比设计模式更为重要,在发展的过程中,设计模式可能在变,但是设计模式依赖于设计原则,设计原则是评判设计模式的标准。

依赖导致原则(DIP)

  • 高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)。
  • 抽象(稳定)不应该依赖于实现细节(变化),实现细节能改依赖于抽象(抽象)。

开放封闭原则(OCP)

  • 对扩展开放,对更改封闭
  • 类模块应该是可扩展的,但是不可修改。

单一职责原则(SRP)

关于类的职责,思考时必须慎之又慎!

  • 一个类应该仅有一个引起它变化的原因。
  • 变化的方向隐含着类的责任。

Liskov替换原则(LSP)

  • 子类必须能够替换他们的基类(IS-A)。
  • 继承表达类型抽象。

接口隔离原则(ISP)

  • 不应该强迫客户程序依赖他们不用的方法。
  • 接口应该小而完备。

优先使用对象组合,而不是类继承

  • 类继承通常为“白箱复用”,对象组合通常为“黑箱复用”。
  • 继承在某种程度上破坏了封装性,子类父类耦合度高。
  • 对象组合则只要求被组合的对象具有良好定义的接口,耦合度底。

封装变化点

  • 使用封装创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。

针对接口编程,而不是针对实现编程

  • 不将变量类型声明为某个特定的具体类,而是声明为某个接口。
  • 客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
  • 减少系统中各部分的依赖关系,从而实现“高内聚,松耦合”的类型设计方案。

面向接口设计,产业强盛的标志:接口标准化

GOF-23模式分类

从目的

  • 创建型(Creational)
  • 结构型(Structural)
  • 行为型(Behavioral)

从范围(实现手段)

  • 类模式(类和子类的静态关系)(继承方案)
  • 对象模式(对象间的动态关系)(组合方案)

从封装变化角度对模式分类:

重构获得模式 Refactoring to Patterns

  • 应对变化,提高复用
  • 发现变化,在变化点处应用设计模式。什么时候、什么地点应用设计模式理解设计模式结构本身更为重要
  • 设计模式应用不宜先入为主。没有一步到位的设计模式。

重构关键技巧:

  • 静态 -> 动态
  • 早绑定 -> 晚绑定
  • 继承 -> 组合
  • 编译器依赖 -> 运行时依赖
  • 紧耦合 -> 松耦合

3.组件协作模式

  • 现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。
  • 典型模式
    • Template Method
    • Strategy
    • Observer/Event

Template Method

动机

  • 在软件构件过程中,对于某一项任务,它常常有稳定的整体操作结构,但是个个自步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。
  • 定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override重写)该算法的某些特定步骤。

结构

要点总结

  • Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。使用虚函数的多态性为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。
  • 除了可以灵活对子步骤的变化外,“不要调用我,让我来调用你”的反向控制结构是Template Method的典型应用。
  • 在实现时,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法、纯虚方法),但一般推荐将他们设置为protected方法。

Strategy

动机

  • 在软件构件过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常负责,而且有时候支持不适用的算法也是一个性能负担。
  • 定义一系列算法,把他们一个个封装起来,并且使他们可以相互替换(变化),该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。

结构

要点总结

  • Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。
  • Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要使用Strategy模式。
  • 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。

Observer/Event

动机

  • 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。
  • 定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

结构

要点总结

  • 使用面向对象的抽象,Observer模式使得我们可以独立地改变(改变时,两者不相互影响)目标与观察者,从而使二者之间的依赖关系松耦合。
  • 目标发送通知时,无需指定观察者,通知会自动传播。
  • 观察者自己决定是否需要订阅通知,目标对象对此一无所知。
  • Observer模式是基于事件的UI框架中非常常用的设计模式,是MVC的一个重要组成部分。

最关键的是抽象的通知依赖关系。

4.单一职责

  • 在软件设计中,如果责任划分不清楚,使用继承得到的结果往往都是随着需求变化,子类急剧膨胀,同时充斥着很多重复代码,这时候的关键是划清责任。
  • 典型模式
    • Decorator
    • Bridge

Decorator 装饰模式

动机

  • 在某些情况下,我们可能会“过度的使用继承来扩展对象的功能”,由于继承为类型引入的静态特性,使得这种扩展方式缺少灵活性,并且随着子类的增多,各种子类的组合会导致更多子类的膨胀。
  • 动态(组合)的给一个对象增加一些额外的职责,就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码&减少子类个数)。

结构

要点总结

  • 通过组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,可根据需要扩展多个功能。
  • Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类的所有接口。但是在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另一个Component类。(以后当看到一个类,同时继承和组合父类,那么很多时候就是使用了Decorator设计模式。
  • Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”----即为“装饰”

Bridge 桥模式

动机

  • 由于某些类型的固有的实现逻辑,使得它们具有连个变化的维度,乃至多个维度的变化。
  • 将抽象部分(业务功能)与实现部分(平台实现)分离,使它们可以独立变化。

结构

要点总结

  • Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度变化(子类)。
  • Bridge模式有时候类似于多继承,但是多继承方案往往未被单一职责原则,复用性较差。
  • Bridge模式的应用一般在“两个非常强的变化维度”,当多于两个的变化维度,可以使用Bridge的扩展模式。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容