一、SOLID 设计原则
- 单一职责原则(Single Responsibility Principle)
核心定义:一个方法、一个类,应尽可能只承担一个功能(职责),职责单一可降低耦合、提高可维护性。
通俗示例:以登录功能为例,“验证用户名”和“验证密码”是两个不同的职责,应该分开写在两个方法中,而非合并在一个方法里。这样后续修改密码验证规则时,不会影响用户名验证的逻辑。
- 开放与封闭原则(Open/Closed Principle)
核心定义:软件实体(类、方法、模块)对于扩展是开放的,对于修改是封闭的。即新增功能时,应通过扩展现有代码实现,而非直接修改原有代码,避免破坏原有逻辑。
通俗示例:修改密码功能中,若新增“手机验证码验证”要求,不应直接修改原有的“修改密码”方法,而是扩展一个独立的验证码验证功能,在调用修改密码方法前先调用该验证码功能,既满足新需求,又不改动原有修改密码的核心逻辑。
- 里氏替换原则(Liskov Substitution Principle)
核心定义:子类必须能够替换其基类(父类),且替换后不会影响程序的正常运行。也就是说,父类能做的事情,子类也能做,且行为一致,不能破坏父类的契约。
该原则是面向对象编程(OOP)的基础原则之一,核心是保障继承关系的合理性。虽然函数式开发中继承使用较少,但该原则的“契约一致性”思想,在函数式编程的接口设计、逻辑复用中仍有隐性应用。比如提供一组工具函数,我们通常会希望这组工具函数的参数和返回值格式一致。
- 最小知识原则(Law of Demeter)
核心定义:也称为“迪米特法则”,核心是“高内聚、低耦合”。一个对象应该尽可能少地了解其他对象的内部细节,只与直接关联的对象交互,减少对象间的依赖和耦合,降低维护成本。
通俗示例:将关联性强的方法、属性封装在同一个类中(高内聚),类对外只提供必要的接口,不暴露内部实现细节,避免其他类直接操作其内部属性(低耦合)。
- 接口隔离原则(Interface Segregation Principle)
核心定义:客户端不应被迫依赖它不需要的接口。即对外暴露的接口应“专一化”,每个接口只承担特定的职责,避免冗余接口,客户端只需依赖自己需要的接口即可。
通俗示例:若一个“用户接口”同时包含“登录”“支付”“修改资料”的方法,应拆分为“登录接口”“支付接口”“资料修改接口”,客户端(如登录模块)只需依赖“登录接口”,无需关注支付、资料修改的相关方法。
- 依赖倒置原则(Dependency Inversion Principle)
核心定义:高层模块不应依赖于低层模块,两者都应依赖于抽象;抽象不应依赖于细节,细节应依赖于抽象。简单来说,编程时应面向接口(抽象)编程,而非面向具体的实现类编程,降低模块间的耦合,提高扩展性。
通俗示例:实现“用户登录验证”功能时,不应直接依赖“手机号登录实现类”“账号密码登录实现类”,而是定义一个“登录验证接口”,让具体的登录实现类实现该接口,高层模块只需调用接口方法,后续新增“微信登录”时,只需新增一个实现接口的类,无需修改高层模块逻辑。
二、其他常用设计原则
-
组合优于继承:优先使用“对象组合”的方式实现功能复用,而非继承。继承会增强类之间的耦合(子类依赖父类),而组合是通过关联不同对象实现功能,更灵活、可维护性更强。
-
无环依赖原则(Acyclic Dependencies Principle):模块之间不应存在循环依赖(如A依赖B,B依赖C,C又依赖A)。若出现循环依赖,可通过“中介者模式”“接口抽象”等方式拆分依赖,打破循环。
-
避免过度设计:软件设计的核心是“简单、可扩展”,初期无需过度优化或添加复杂功能,应根据实际需求设计,预留扩展空间即可。过度设计会增加开发、维护成本,反而降低效率。
一、SOLID 设计原则
核心定义:一个方法、一个类,应尽可能只承担一个功能(职责),职责单一可降低耦合、提高可维护性。
通俗示例:以登录功能为例,“验证用户名”和“验证密码”是两个不同的职责,应该分开写在两个方法中,而非合并在一个方法里。这样后续修改密码验证规则时,不会影响用户名验证的逻辑。
核心定义:软件实体(类、方法、模块)对于扩展是开放的,对于修改是封闭的。即新增功能时,应通过扩展现有代码实现,而非直接修改原有代码,避免破坏原有逻辑。
通俗示例:修改密码功能中,若新增“手机验证码验证”要求,不应直接修改原有的“修改密码”方法,而是扩展一个独立的验证码验证功能,在调用修改密码方法前先调用该验证码功能,既满足新需求,又不改动原有修改密码的核心逻辑。
核心定义:子类必须能够替换其基类(父类),且替换后不会影响程序的正常运行。也就是说,父类能做的事情,子类也能做,且行为一致,不能破坏父类的契约。
该原则是面向对象编程(OOP)的基础原则之一,核心是保障继承关系的合理性。虽然函数式开发中继承使用较少,但该原则的“契约一致性”思想,在函数式编程的接口设计、逻辑复用中仍有隐性应用。比如提供一组工具函数,我们通常会希望这组工具函数的参数和返回值格式一致。
核心定义:也称为“迪米特法则”,核心是“高内聚、低耦合”。一个对象应该尽可能少地了解其他对象的内部细节,只与直接关联的对象交互,减少对象间的依赖和耦合,降低维护成本。
通俗示例:将关联性强的方法、属性封装在同一个类中(高内聚),类对外只提供必要的接口,不暴露内部实现细节,避免其他类直接操作其内部属性(低耦合)。
核心定义:客户端不应被迫依赖它不需要的接口。即对外暴露的接口应“专一化”,每个接口只承担特定的职责,避免冗余接口,客户端只需依赖自己需要的接口即可。
通俗示例:若一个“用户接口”同时包含“登录”“支付”“修改资料”的方法,应拆分为“登录接口”“支付接口”“资料修改接口”,客户端(如登录模块)只需依赖“登录接口”,无需关注支付、资料修改的相关方法。
核心定义:高层模块不应依赖于低层模块,两者都应依赖于抽象;抽象不应依赖于细节,细节应依赖于抽象。简单来说,编程时应面向接口(抽象)编程,而非面向具体的实现类编程,降低模块间的耦合,提高扩展性。
通俗示例:实现“用户登录验证”功能时,不应直接依赖“手机号登录实现类”“账号密码登录实现类”,而是定义一个“登录验证接口”,让具体的登录实现类实现该接口,高层模块只需调用接口方法,后续新增“微信登录”时,只需新增一个实现接口的类,无需修改高层模块逻辑。
二、其他常用设计原则
组合优于继承:优先使用“对象组合”的方式实现功能复用,而非继承。继承会增强类之间的耦合(子类依赖父类),而组合是通过关联不同对象实现功能,更灵活、可维护性更强。
无环依赖原则(Acyclic Dependencies Principle):模块之间不应存在循环依赖(如A依赖B,B依赖C,C又依赖A)。若出现循环依赖,可通过“中介者模式”“接口抽象”等方式拆分依赖,打破循环。
避免过度设计:软件设计的核心是“简单、可扩展”,初期无需过度优化或添加复杂功能,应根据实际需求设计,预留扩展空间即可。过度设计会增加开发、维护成本,反而降低效率。