设计模式5大原则总结

设计模式的原则通常被总结为5大原则,这五大原则在设计模式领域中被广泛接受和应用,它们是:

单一职责原则 (SRP, Single Responsibility Principle):一个类或者模块应该有且仅有一个改变的理由。
开放封闭原则 (OCP, Open/Closed Principle):软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。
里氏替换原则 (LSP, Liskov Substitution Principle):子类应当能够替换掉它们的基类并且不影响程序的正确性。
依赖倒置原则 (DIP, Dependency Inversion Principle):依赖于抽象而不是具体实现,高层模块不应依赖于底层模块,二者都应该依赖于抽象。
接口隔离原则 (ISP, Interface Segregation Principle):客户端不应该依赖它不需要的接口,即接口应该尽可能小且专注于单一职责。

五大原则首字母拼起来正好是SOLID

一、开闭原则

定义:一个软件实体(如类、模块或函数)应当对扩展开放,对修改关闭。也就是说,当需求变化时,应优先通过添加新代码而非修改现有代码来实现功能的扩展。

分析:开闭原则(OCP)是软件设计中最基础和最宽泛的原则之一,它强调了软件实体应对扩展开放,对修改封闭的理念,即尽量保证原有代码的稳定性和降低因需求变更带来的风险。

优点:

  1. 稳定性:想象一下,一段稳定运行的核心代码因为新增需求要修改,是不是风险很大?

  2. 可维护性:对于新需求,你是愿意在别人已经稳定运行的代码上(或者屎山上)修改呢,还是新增方法或者类来实现呢?

  3. 单元测试:辛辛苦苦把单元测试覆盖率提高上去了,结果一个需求导致单测都fail了,是不是很崩溃?

综上所述,遵循开闭原则能够促进软件工程中的良好实践,确保软件随着时间推移仍能保持良好的结构和健康的生命力,进而提升软件的整体质量和开发团队的,因此,在代码设计时就要考虑以后的功能扩展,典型的应用有策略模式、装饰者模式等。

二、单一职责原则

定义:一个类或者模块应该只有一个引起它变化的原因。换句话说,一个类应该只有一个职责,当且仅当这个类的一个职责发生变化时,才会去修改这个类。

分析:维度可以是方法、类、包或者项目

优点:

     1 提高可读性:你是愿意通过方法名称就能读懂方法的作用呢,还是看到冗长的代码不知所云呢?
     2 提高可维护性:由于很多功能耦合在一个类或者方法上,每次新增或者变更需求都要在原有的代码上修改,是不是很崩溃?
    3 提高复用性:粒度越小的方法越容易被复用
    4 降低单元测试的难度:粒度越小越容易写单测,相反,过于复杂的代码甚至会导致单元测试无从下手

总结:单一职责原则有助于构建松耦合、高内聚的系统,使得代码更加简洁、可读性强、易于理解和维护,并能够有效应对需求变化带来的挑战。典型的应用有建造者模式、工厂模式等。

三、依赖倒置原则

定义:高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

分析:定义听起来比较晦涩,实际就是不要直接依赖具体实现,而是依赖接口。是开闭原则的一种具体实现方式。

高层模块:通常指的是那些离业务逻辑较近,更接近最终用户需求或者更靠近系统顶层入口的模块。这类模块负责定义系统整体架构、主要流程控制和业务逻辑的组织协调。在面向对象设计中,高层模块可能包含控制器、服务层中的聚合服务等组件,它们调用其他模块来完成复杂的业务操作。

低层模块:是指那些更接近系统基础设施,实现具体细节和操作的模块。它们通常负责数据访问、算法实现、资源管理等较为底层的操作,为高层模块提供服务。在面向对象设计中,低层模块可能包括数据访问层(DAO)、模型层中的具体实现类、工具类等。

在传统的自底向上设计中,高层次的模块往往会直接依赖于低层次模块的具体实现。然而,在依赖倒置原则指导下,高层模块不应直接依赖于低层模块的具体类,而是依赖于抽象接口或者抽象类。

这样做的目的就是把实现细节下沉,而上层组件通过对接口进行操作,这样即使底层的具体实现发生变化,只要接口不变,上层组件就不受影响。

同时,具体实现类应该依赖于抽象接口,通过实现接口来完成任务,这样就实现了依赖方向的倒置。

优点:

  1. 增强可扩展性和可维护性:比如策略模式中的上下文,执行策略的方法接受的是策略的抽象接口,这样只要客户端传入不同的具体策略,上下文就能执行相应策略的方法,而无需修改上下文,轻松实现替换或新增具体实现类。

  2. 松散耦合:由于依赖的是接口,底层具体实现的改变不会影响到高层模块,降低耦合度,提高系统的稳定性

  3. 方便单元测试:由于依赖的是接口,高层模块的单测不受低层模块变化的影响,同时可以轻易地替换依赖的具体实现。

总结:依赖倒置原则强调了设计时应关注抽象和接口,以此来解耦系统中的不同组件,从而达到增强系统稳定性、可扩展性和可维护性的目标。通过依赖抽象,而不是具体的实现,软件系统能够更好地适应变化,减少修改引发的连锁效应,实现开闭原则的核心思想。

四、接口隔离原则

定义:接口隔离原则主张不应该强迫客户端依赖它们不需要的方法,即接口应该是轻量级的,包含一组相关的方法,而不是一个庞杂的大接口。应该根据客户端的实际需求来划分接口,使其只包含客户端真正需要用到的方法。

分析:可以看作单一职则原则的一种实现方式,有助于编写高内聚低耦合的代码

优点:

基本上等同于单一职则的优点

1 避免接口污染: 子类无需实现自身不需要的方法

2 提高内聚: 高内聚的有助于提高代码的可读性和可维护性,试想一个业务散落在各个地方,难以理解不说,改动起来还容易遗漏,出现bug的几率也更大

3 降低耦合度: 减少了接口变更对其它无关模块的影响

4 提高复用性: 粒度越小越容易复用

5 单元测试: 粒度越小越容易单测

五、里式替换原则

在软件设计中,一个对象应该能够在其所属的类型体系中被替换为其父类型的任何实例而不会引起程序行为的改变。也就是说,如果有两个类型T1和T2,并且T2是T1的子类型,那么在所有针对T1类型的程序上下文中,均可用T2类型的对象来替代T1类型的对象,而且预期的行为不变。

优点
1. 增强程序的健壮性:遵循里式替换的设计可以使代码更加稳定,因为对父类的修改不会意外地影响到子类的行为,从而减少了因修改父类而导致的潜在错误扩散。

2. 支持多态性:通过保证子类对父类接口的正确实现,里氏替换原则促进了多态性的运用,使得程序可以在不更改原有逻辑的情况下接纳新类型的对象。

3. 降低耦合度:遵循里式替换可以使父类和子类之间的耦合度降低,父类无需了解子类的具体实现细节,只需要依赖于共同的接口或抽象。

4. 提高可扩展性和复用性:遵循里式替换设计的子类可以在不破坏现有系统的基础上增加新的功能,同时保持与父类的兼容性,这样既扩展了系统的功能,也增强了已有代码的复用程度。

5. 遵循开闭原则:作为 SOLID 设计原则的一部分,LSP有助于实现开闭原则,即对扩展开放,对修改封闭。通过合理的继承结构和符合LSP的子类设计,系统可以在不修改原有代码的基础上添加新的功能。

简单来说,一个良好的继承关系应当确保任何时候都可以用子类安全地替换父类,而不会影响程序的正确性。这就要求子类不能改变父类原有的约定,包括前置条件(即调用方法所需的条件)不能比父类更严格,后置条件(即方法结束后的保证)不能比父类更弱,以及其他不变条件(如抛出的异常)也不能超出父类所规定的范围。

在某些文献和讨论中,也会将设计原则扩展到7种,额外增加了以下两条原则,分别是迪米特法则:一个对象应当对其他对象有最少的了解,也称为最少知识原则,典型的应用有外观模式以及中介者模式。合成复用原则:尽量使用对象组合而非类继承达到复用的目的,典型的应用有桥接模式。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值