0%

设计模式

设计模式简介

1、当使用抽象思维,涉及到类的继承和虚函数时,必须使用虚析构函数,原因如下:
——1、虚析构函数可以确保正确的析构函数序列被调用。
——2、如果析构函数不是虚的,则将只能调用对应于指针类型的析构函数。这意味着只有基类的析构函数被调用,即使指针指向的是一个派生类对象。
——3、如果析构函数是虚的,将调用相应对象类型的虚构函数。因此,如果指针指向的是派生类对象,将调用派生类对象的析构函数,然后自动调用基类的析构函数。
2、当使用抽象思维,涉及到类的继承并且使用模板类时,模板参数最好设置成基类指针,因为基类指针可以指向基类或是派生类对象,而如果不使用指针为模板参数,则将会导致任何被送入此模板的对象被切割为基类对象。因为模板参数是基类的指针,所以push对象进模板的时候必须使用new给它分配空间。但既然使用了new,一定不要忘记delete。

面向对象设计原则

1、宏观上隔离变化,将变化所带来的影响减为最小。
2、微观上各个类各司其职,由于需求变化导致的新增类型不应该影响原来类型的实现。

面向对象设计原则(1)——依赖倒置原则(DIP)

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

面向对象设计原则(2)——开放封闭原则(OCP)

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

面向对象设计原则(3)——单一职责原则

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

面向对象设计原则(4)——Liskov替换原则(LSP)

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

面向对象设计原则(5)——接口隔离原则(ISP)

1、不应该强迫客户程序依赖它们不用的方法。
2、接口应该小而完备。

面向对象设计原则(6)——优先使用对象组合,而不是类继承

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

面向对象设计原则(7)——封装变化原则

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

面向对象设计原则(8)——针对接口编程,而不是针对实现编程

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

重构关键技法

1、静态->动态
2、早绑定->晚绑定
3、继承->组合
4、编译时依赖->运行时依赖
5、紧耦合->松耦合

模板方法

“组件协作”模式

模板方法的动机

对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。

调用关系

调用->被调用 Library写的早,main函数写的晚
Application->Library 写的晚的调用写的早的,叫做早绑定。
Library->Application 写的早的调用写的晚的,叫做晚绑定。

模板模式定义

定义一个操作中算法的骨架(稳定),而将一些步骤(变化)延迟到子类中(定义一个虚函数然后让子类去实现)。模板方法使得子类可以不改变(复用)一个算法的结构即可重定义(重写)某些特定步骤。

模板模式注意

1、稳定的代码部分要写成非虚函数,支持变化的代码部分要写成虚函数。
2、必须要有一个稳定点,没有稳定就没有复用。
3、具体实现例子是在基类中定义一个骨架,即一个Run函数,为子类留下虚方法供其变化。
4、学习任何设计模式,都要画一个类图,看看这个模式里面哪些是稳定的,哪些是变化的。

模板模式缺点

应用程序开发人员(实现子类的人员)不容易接触并了解程序的骨架。

模板模式总结

1、该模式中稳定的是Run函数部分,变化的是子类中对虚函数的实现。
2、非常基础性的设计模式,它用最简洁的机制(虚函数的多多态性),为很多应用程序框架提供了灵活的扩展点。
3、模板方法的典型应用是站在library类的角度上,“不要调用我,让我来调用你”的反向控制结构。
4、被模板方法调用的方法可以有实现,也可以没有任何实现(抽像方法、纯虚方法)。一般推荐把它们设置为protected方法。

策略模式

“组件协作”模式

策略模式的动机

在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。

策略模式定义

定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。

策略模式总结

1、该模式中稳定的是抽象基类和Strategy类(也就是使用基类的类)是不变的,变化的是子类的算法和种类。
2、Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。
3、Strategy模式提供了用条件判断语句以外的另一种选择。消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。
4、如果代码中出现if else 语句就是代码需要使用策略模式的标志。但在if else 是绝对不会变的,比如一周的七天,可以使用if else。
5、如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。

观察者模式

“组件协作“模式

观察者模式的动机

1、在软件构建过程中,我们需要为某些对象建立一种”通知依赖关系“——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
2、使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定地依赖关系。从而实现软件体系结构的松耦合。