欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

设计原则的简单理解

程序员文章站 2024-01-20 17:08:52
前言 好的代码需要有高内聚、低耦合、易扩展且扩展改动小等特点。说实话,我入行很久之后,才知道这些设计原则的名字,但是我并不觉得陌生,反而有一种理所当然的感觉。这得感谢自学时网络上前辈们推荐的书籍,培养了自己的代码洁癖,还得感谢转行后的第一个东家!以下只是我的理解,如有错误,请指正。 单一职责原则 顾 ......

前言

好的代码需要有高内聚、低耦合、易扩展且扩展改动小等特点。说实话,我入行很久之后,才知道这些设计原则的名字,但是我并不觉得陌生,反而有一种理所当然的感觉。这得感谢自学时网络上前辈们推荐的书籍,培养了自己的代码洁癖,还得感谢转行后的第一个东家!以下只是我的理解,如有错误,请指正。

单一职责原则

顾名思义,单一职责就是函数或类只做一件事,但是"只做一件事"肯定是针对不同抽象层次的。
举个例子,我要写一个文件,于是我定义了write()这么一个函数,它确实只做一件事。但是这个write()对于写一个文件来说是不够的,我肯定还需要open()close(),自然这两个函数也只做了一件事。
但我要真正写一个文件,希望得到的是下面的函数

int write_file()
{
    open();
    write();
    close();
}

对于write_file()的调用者来说,write_file()确实只做了一件事,它帮我写了一个文件。但对于写write_file()的程序员来说,write_file()明明做了三件事。
单一职责的职责是对外抽象后的职责,只要函数或类所做的事不超过这个抽象定义,那就不算违背单一职责。

越底层的函数越容易确定职责,甚至只需要这个函数写的足够短小,其职责一般就能保证单一。高层的函数或者类就需要考验程序员的抽象能力了。一个简单的检查该抽象是否能做到单一职责的方法,就是看看函数内是否只做了函数名要求的事,类内所有成员函数和成员变量是否只是为了做到类名要求的事。

当我们长期遵循单一职责原则时,我们会习惯于将一个任务拆分为多个最小步骤,而这通常意味着可以通过流水线,并行等方式来执行这些最小步骤,达到提升性能的目的。

里氏替换

里氏替换就是指子类可以出现在父类出现的任何地方。这是一个指导我们何时使用继承的原则。a继承b,我们说"a是一个b",既然"a是一个b",a自然能替换到b出现的任何地方。如果无法替换的话,说明a不应继承b。

依赖倒置

依赖倒置就是为了做到面向接口编程。
那为什么叫倒置呢?原本高层a直接调用底层b的接口,当高层a想用底层c时就可能需要修改大量代码,原因是c和b是没有约束的,c的接口与b可能完全不一样。为了避免替换底层需要修改大量代码的情况,高层a自己定义了抽象层d,让底层b和底层c都依赖抽象层d的接口去实现。因为抽象层d是高层定义的,而底层b和c是依赖d去实现的,所以就叫依赖倒置。在c++中,这通过定义虚基类,并继承该虚基类来实现。

依赖倒置可以使得高层切换底层实现类时,减少代码修改量,只需要修改一下实例化的代码即可,更灵活。

class d
{
public:
    virtual foo1() = 0;
    ...
    virtual foon() = 0;
}
class b : public d;
class c : public d;
void a()
{
    d* a = new b; // 切换为c时,只需要修改这一行代码。
    a->foo1();
    ...
    a->foon();
}

接口隔离原则

接口隔离是针对接口调用者做的隔离,只让调用者看到其能调用的接口,本质上是最小权限。大部分it公司都会宣讲信息安全,而为了保证信息安全的一个原则就是最小化原则。接口隔离就是为了程序安全,如果提供了超过调用者权限的接口,那可能就会引发问题。

迪米特法则

迪米特法则就是最小依赖,依赖更少的类,更少的接口,这样可以降低类之间的耦合和减少代码复杂度。如果某个类依赖了很多类,很多接口,那以后其代码就有更大的可能因为其依赖项的改动而改动,变得不稳定。

开闭原则

对扩展开放,对修改闭合。扩展可以是函数的扩展,也可以是类的扩展,这里的对修改闭合指的是对本层的修改闭合,因为对于高层来说肯定是需要修改的,比如调用新接口,使用新类的实例。之所以对修改闭合,是为了避免修改引入bug。

后话

总是遵顼这些设计原则,对自己的代码能力是有很大益处的。再者设计原则是道,设计模式是术,如果对道理解通透的话,术是可以自行推演的,可能不知不觉中你已经用了某种设计模式了,甚至创造了新的设计模式。