面向对象设计原则

面向对象最大的优势是抵御变化

理解隔离变化

  • 从宏观面来看,面向对象构建方式更能适应软件的变化,能将变化所带来的影响减为最少。
    各司其职
  • 从微观层面来看,面向对象的方式更强调各个类的责任。
  • 由于需求变化导致的新增类型不应该影响原来类型的实现。
    对象是什么?
  • 从语言实现层面来看,对象封装了代码和数据。
  • 从规格层面来讲,对象是一系列可被使用的公共接口。
  • 从概念来讲,对象是某种拥有责任的抽象。

面向对象设计原则

依赖倒置原则(DIP):

  • 高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)。
  • 抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象(稳定)
    理解:
    用第一篇文章中的代码为例 - 文章
    MainForm 依赖于 Shape,Line和Rect也都依赖于Shape。这个Shape就是抽象。抽象不应该依赖于实现细节,也就是抽象不应该去依赖于子类,因为抽象是稳定的,不应该去依赖一个变化的东西。
    这里 Shape 是稳定的, Line、Rect 是变化的,我们通过 Shape 实现了隔离变化。
开放封闭原则(OPC):
  • 对拓展开发,对更改封闭。
  • 类模块应该是可拓展的,但是不可修改。

在之前的文章中,如果需要增加一个圆形或其他图形,是需要做出改变的,例如:


    std::vector<Line> lineVector;
    std::vector<Rect> rectVector;
    增加的会将会新增
    std::vector<Circle > circleVector;

如果这里进行修改,那么就意味着对这个部分进行重新编译,测试和部署。
如果基于开发封闭原则,那么我们增加圆形的话,按照 对更改封闭的思想,新的方法中使用了 vector shapeVector; 它是不需要改变,它也是以拓展的方式,应对了新的需求。

单一职责原则(SRP):
  • 一个类应该仅有一个引起它变化的原因。
  • 变化的方向隐含着类的责任。
Liskov 替换原则(LSP):
  • 子类必须能够替换它们的基类(IS-A)。
  • 继承表达类型抽象。
接口隔离原则(ISP):
  • 不应该强迫客户程序依赖它们不用的方法。
  • 接口应该小而完备。

如果子类就 protected ,如果本类就 private ,如果真正有必要的情况,需要暴漏出去才使用 public。 因为如果一个类的成员你大量使用 public 暴漏出去,那么使用它的客户程序就会对齐产生依赖,一旦产生依赖了,那么你修改接口,客户程序也需要对应的大量修改。

优先使用对象组合,而不是类继承
  • 类继承通常为“白箱复用”,对象组合通常为“黑箱复用”。
  • 继承在某种程度上破坏了封装性,子类父类耦合度高。
  • 而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。
封装变化原则
  • 使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。
针对接口编程,而不是针对实现编程
  • 不将变量类型声明为某个特定的具体类,而是声明为某个接口。
  • 客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
  • 减少系统中各部分的依赖关系,从而实现“高内聚、松耦合”的类型设计方案。

例如这部分代码就一直依赖具体类型

vector<Line> lineVector;
vector<Rect> rectVector;
//改变
vector<Circle> circleVector;

下面则是面向接口设计,直接放对应的抽象接口,处理的时候只使用接口的通用方法即可:

//针对所有形状,并不需要针对单个图形
vector<Shape*> shapeVector;

你可能感兴趣的:(设计模式,设计模式)