侯捷-C++设计模式 笔记(已更新设计模式2个)

侯捷-C++设计模式 笔记(已更新设计模式2个)
一、 设计模式简介1.课程目标松耦合设计思想面向对象设计原则重构技法改善设计GOF核心设计模式2.什么是设计模式每一个模式描述了一个在我们周围不断重复发生的问题以及该问题的解决方案的核心。这样你就能一次又一次地使用该方案而不必做重复劳动。3.从面向对象谈起底层思维向下如何把握机器底层从微观理解对象构造语言构造编译转换内容模型运行时机制抽象思维向上如何将我们周围世界抽象为程序代码面相对象组件封装设计模式架构模式4.深入理解面相对象向下深入理解三大面相对象机制封装隐藏内部实现 继承复用现有代码 多态改写对象行为向上深刻把握面相对象机制所带来的抽象意义理解如何使用这些机制来表达现实世界掌握什么是“好的面相对象设计”5.抽象思维的背景软件设计固有的复杂性建筑商从来不会去给一栋已建好的100层高的楼房底下再新修一个小地下室——这样做花费极大而且注定要失败。然而令人惊奇的是软件系统的用户在要求做出类似改变时却不会仔细考虑而且他们认为这只是需要简单编程的事。 ——Object-Oriented Analysis and Design with Applications6.软件设计复杂的根本原因变化客户需求的变化 技术平台的变化 开发团队的变化 市场环境的变化7.如何解决复杂性分解 人们面对复杂性有一个常见的做法即分而治之将大的问题分解为多个小问题将复杂的的问题分解为多个简单问题。抽象 更高层次来讲人们处理复杂性有一个通用的技术即抽象。由于不能掌握全部的复杂对象我们选择忽视它的非本质细节而去处理泛化和理想化了的对象模型。示例图形绘制代码来对比结构化和面向对象编程的区别点线矩形虚析构函数C中的public继承方式8.软件设计的目标什么是好的软件设计软件设计的金科玉律复用二、面向对象设计原则1.为什么要使用面向对象设计变化是复用的天敌面相对象设计的最大优势在于抵御变化2.重新认识面向对象理解隔离变化 从宏观层面来看面相对象的构建方式更能适应软件的变化能将变化所带来的影响减少为最小。 各司其职 从微观层面来看面相对象的方式更强调个各类的“责任” 由于需求变化导致的新增类型不应该影响原有类型的实现——是所谓各负其责 对象是什么 从语言层面来看对象封装了代码数据 “这里不准确应该是操作和数据” 从规格层面讲对象是一系列可被使用的公共接口 从概念层面讲对象是某种拥有责任的抽象“设计模式是针对有稳定点和稳定点的情况。分离稳定和变化把变化关闭到笼子里。对于完全变化和完全稳定都不需要设计模式。”3.面相对象设计原则1设计原则是一把尺子去评判设计时候合理。” 依赖倒置原则DIP 高层模块稳定不应该依赖于底层模块变化二者都应该依赖于抽象稳定 MainForm不应依赖于Line、Rect而应该都依赖于Shape 抽象稳定不应该依赖于实现细节变化实现细节应该依赖于抽象稳定4.面相对象设计原则2开放封闭原则OCP 对扩展开放对更改封闭 类模块应该是可扩展的但是不可修改5.面相对象设计原则3单一职责原则SRP 一个类应该仅有一个引起它变换的原因。 变换的方向隐含着类的责任6.面相对象设计原则4Liskov替换原则LSP 子类必须能够替换它们的基类IS-A 继承表达类型抽象7.面相对象设计原则5接口隔离原则ISP 不应该强迫客户程序依赖它们不同的方法 接口应该小而完备8.面相对象设计原则6优先使用组合而不是类继承 类继承通常为“白箱复用”对象组合通常为“黑箱复用” 继承在某种程度上破坏了封装性子类父类耦合度高 而对象组合则只要求被组合的对象具有良好定义的接口耦合度低。9.面相对象设计原则7封装变化点 使用封装来创建对象之间的分界层让设计者可以在分界层的一侧进行修改而不会对另一侧产生不良影响 从而实现层次间的松耦合10.面相对象设计原则8针对接口编程而不是针对实现编程 不将变量类型声明为某个特定的具体类而是声明为某个接口。 客户程序无需获知对象的具体类型只需要知道对象所具有的接口。 减少系统中各部分的依赖关系从而实现“高内聚、低耦合” 的类型设计方案。 “面相接口设计产业强盛的标志接口标准化” “如秦朝兵器都有统一的标准” “毕升的活字印刷术”11.将设计原则提升为设计经验设计习语 Design Idioms Design Idioms描述与特定编程语言相关的低层模式技巧惯用法 设计模式 Design Patterns Design Patterns主要描述的是“类与相互通信的对象之间的组织关系包括它们的角色职责协作方式等方面。 架构模式 Architectural Patterns Architectural Patterns描述系统中与基本结构组织关系密切的高层模式包括子系统划分职责以及如何组织它们之间关系的原则三、模版模式1.GOF-23模式分类从目的来看创建型Creational)模式将对象的部分创建工作延迟到子类或者其他对象从而应对需求变化为对象创建时具体实现引来的冲击结构型Structural模式通过类继承或者对象组合获得灵活的结构从而应对需求变化为对象的结构带来的冲击行为型Behavioral模式通过类继承或者对象组合来划分类与对象间的职责从而应对需求变化为多个交互的对象带来的冲击从范围来看类模式处理类与子类的静态关系对象模式处理对象间的动态关系2.从封装的角度对模式分类组件协作Template MethodStrategyObserver/Event单一职责DecoratorBridge对象创建Factory MethodAbstract FactoryPrototypeBuilder对象性能SingletonFlyweight接口隔离FacadeProxyMediatorAdapter状态变化MementoState数据结构CompositeIteratorChain ofResposibility行为变化CommandVisitor领域问题Interpreter3.重构获得模式 Refactoring to Patterns面向对象设计模式是“好的面相对象设计”所谓“好的面相对象设计”指是哪些可以满足“应对变化提高复用的设计”现代软件设计的特征是“需求的频繁变化”设计模式的要点是“寻找变化点让后在变化点处应用设计模式从而更好的应对需求的变化”“什么时候什么地点应用设计模式比理解设计模式结构本身”更为重要。设计模式的应用不宜先入为主一上来就是用设计模式是对设计模式的最大误用。没有一步到位的设计模式敏捷软件开发时间提倡的“Rectoring to Patterns”是目前普遍公认的最好的使用设计模式方法。4.推荐书籍5.重构关键技法静态-动态早绑定-晚绑定继承-组合编译时依赖-运行时依赖紧耦合-松耦合6.组件协作模式现代软件专业分工之后的第一个结果是“框架与应用的划分”“组件协作”模式通过晚期绑定来实现框架与应用程序之间的松耦合是二者之间协作时常用的模式。典型的模式Template MethodStrategyObserver/Event;7.Template Method 模式的动机(Motivation)在软件构建过程中对于某一项任务它常常有稳定的整体操作结构但各个子步骤却有很多改变的需求或者由于固有的原因比如框架与应用之间的关系而无法和任务的整体结构同时实现。如何在确定稳定操作结构的前提下来灵活应对各个子步骤的变化或者晚期实现需求#pragma region 模版模式 class Library { public: virtual bool Step2() 0; // 抽象步骤 virtual void Step4() 0; // 抽象步骤 void Step1() {/*执行固定步骤*/ } void Step3() {/*执行固定步骤*/ } void Step5() {/*执行固定步骤*/ } void Run() { Step1(); if (Step2()) { Step3(); } for (int i 0; i 3; i) Step4(); Step5(); } }; class Application : public Library { bool Step2() override { // 实现具体步骤2 return true; } void Step4() override { // 实现具体步骤4 } }; //将固定的框架步骤封装到基类库中应用程序只需实现具体步骤从而实现代码复用和灵活扩展。 int main() { Application app; app.Run(); return 0; } #pragma endregion 模版模式模版模式这种框架的库程序调用应用程序的晚完成的程序叫晚绑定反之叫早绑定。8.模式定义定义一个操作中的算法的骨架稳定而将一些步骤延迟变化到子类中。Template Method使得子类可以不改变复用一个算法的结构即可重定义override重写该算法的某些特定步骤。————《设计模式》 GoF设计模式的核心是分离变化点隔离变化点。把变化点像小兔子一样关起来。相反需求所有的都变化或者都固定 都不适合任何设计模式。Windows API 实现窗口编程 和 MFC的实现是典型的由早绑定编程变为晚绑定的变化过程。9.结构10.总结Template Method 模式是一种非常基础性的设计模式在面向对象系统中有着大量的应用。他用最简洁的机制虚函数的多态性为很多应用程序框架提供了灵活的扩展点是代码复用方面的基本实现结构。处理可以灵活应对子步骤的变化外“不要调用我让我来调用你”的反向控制结构是Template Method的典型应用。在具体实现方面被Template Method调用的虚方法可以具有实现也可以没有任何实现抽象方法、纯虚方法但一般推荐它们设置为protected方法。四、策略模式1.动机在软件狗之间过程中某些对象使用的算法可能多种多样经常改变如果将这些算法都编码到对象中将会使对象变得异常复杂而且有时候支持不使用的算法也是一个性能负担。如何在运行时根据需要透明底更改对象的算法将算法与对象本身解耦从而避免上述问题面向对象中说的复用是指二进制层面的编译层面的复用而不是源代码级别的复用2.定义定义一些列算法把它们一个个封装起来并且使它们可互相替换变化。该模式使得算法可独立于使用它的客户程序稳定而变化扩展子类化。3.结构4.总结Strategy及其子类为组件提供了一系列可重用的算法从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。Strategy模式提供了用条件判断语句以外的另一种选择消除条件判断语句就是在解耦合。含有许多条件判断语句的代码通常都是需要Strategy模式。如果Strategy对象没有实例变量那么各个上下文可以共享同一个Strategy对象从而节省对象开销。