870920 Menu

小小的说明之二:关于设计原则

随着对JUCE类库的介绍不断深入与具体,为了从更高的层次描述清晰,减少废话,让读者更宏观、更直接的了解此库,不可避免的会牵扯到类库设计、面向对象设计原则与设计模式(我会尽量避免)。实际上,有些方面,并无严格的统一与定论,甚至有争议,或自相矛盾。为避免误解和歧义,此处简单补充一下我所理解和体会的原则、模式等等,敬请批评指正。

严格说起来,这篇文章不能算是原创。更多,类似于依托于书本及经典,个人的读书笔记。或者说是不揣冒昧、厚颜无耻地总结大师经验而已。当然,多多少少,也有一点个人的实践体会在里面。只是,和前人智慧比起来,完全可以忽略。

关于面向对象设计原则

指导思想:抽象及重用。现实为基,抽象为本。便于理解,可以重用。

总的原则:高内聚,低耦合。便于扩展(容易将新功能添加到现有系统中)。使用灵活(修改代码时不会波及其他模块)。可插入性(可以很方便的将某个或某些类抽取出来,同时将另一个有相同接口的类添加进来)。

设计目标:最小复杂度,减少关注点,分解和隔离,松散耦合,面对未来的可扩展性,可重用性,高扇入、低扇出。可移植性,精简性,层次性。

七大原则:

  1. 单一职责:不要将太多的职责(功能)放在一个类中。实现高内聚、低耦合的指导方针。
  2. 开闭原则:软件实体应对扩展开放,对修改关闭。实体可以是一个系统模块,一组类或一个独立的类。具体实践中,通常是确定基类,通过派生子类来扩展或修改基类的功能。使用继承关系完成抽象到具体的转换,针对基类接口进行编程。
  3. 里氏代换:使用继承方式创建新类时,要严格遵守此原则,即:所有使用基类对象之处,皆可以子类对象代之。将基类对象替换为子类对象,程序不会产生任何错误和异常,但反之不成立。编程时,尽量使用基类类型进行定义,运行时再绑定具体的子类。这些属于面向对象多态性的一种灵活运用。使用里氏代换需注意两点:一是子类的所有方法必须在基类中声明,否则,需借助强制类型转换来调用基类中没有的方法。严格来说,这样并不符合里氏代换。二是尽量将基类抽象出来。
  4. 依赖倒转:系统抽象化的具现,即尽量针对抽象类的方法编程,而不要针对具体类的方法进行编程。里氏代换是依赖倒转的基础。在以类的对象进行传参时,尽量将该参数声明为抽象类的指针或引用,而不要声明为具体类的对象。这种方式也可称为“依赖式注入”,具体有3种情况:构造注入,设置注入,接口注入。
  5. 接口隔离:单一职责的另一种体现。如果某个类的功能和接口太多太大,则将其分割成多个小类。也适用于某个具体的函数。实际上是为了实现单一职责。
  6. 合成复用:创建新类时尽量使用组合或聚合的方式(其他类的对象作为新类的数据成员或临时调用),少用或不用继承。这也是为了实现低耦合与高内聚,减少外部依赖(继承是最强的依赖)。
  7. 迪米特法则:不要与陌生人说话,只与最密切相关的类直接通信。即每个类都要尽量少的与其他类发生直接交互。这也是为了提高封装内聚,减少耦合依赖。如果必须与其他关系不紧密的类通信,则通过组合的方式用第三者来转发调用。