当前位置: 首页 > 后端技术 > Node.js

经典设计原则——SOLID

时间:2023-04-03 12:23:52 Node.js

SOLID设计原则包括以下五个原则:单一职责原则(SRP)、开闭原则(OCP)、里氏代换原则(LSP)、接口隔离原则(InterfaceSegregationPrinciple,ISP)依赖倒置依赖倒置原则(DependencyInversionPrinciple,DIP)单一职责原则理解,单一职责原则的描述是一个类或模块只负责完成一个职责(或功能)。当然,单一职责原则不仅适用于模块或类,还适用于很多粒度,如函数、类、接口、模块等,而模块通常由多个类组成。责任可以参考模块变更的原因。从这个角度来看,单一职责原则意味着模块更改的原因不应该超过一个。需要注意的是,不同的应用场景、不同阶段的需求背景、不同的业务层级,对同一个类的职责是否单一的判断结果可能不同。优点遵循单一职责原则,会有以下优点:提高代码可维护性:职责更少,复杂度更低,可读性更好,可维护性更高降低代码变更风险:职责越多,代码变更的可能性越高,变化的风险更大。最佳实践在实际开发中,可能会出现以下现象违反单一职责原则:一个模块中的变量、属性或代码行过多。内部和外部依赖关系太多。模块中的私有方法太多。很难给模块一个合理的名字。模块的大部分操作只针对少数几个属性。如果出现上述情况,需要判断是否将代码分离,遵循单一职责原则,最终目标应该是提高内聚,降低耦合,保证代码可维护性。开闭原则理解开闭原则指出软件实体(模块、类、方法等)应该“对扩展开放,对修改关闭”。详细解释就是在添加新功能时,代码是在现有代码的基础上进行扩展(添加模块、类、方法等),而不是修改现有代码(修改模块、类、方法等)。).更宽泛的理解是以最少的代码修改为代价完成新功能的开发。优点遵循开闭原则,会有以下优点:缩小测试范围:修改代码的范围越小,涉及的测试范围越小,未修改的测试代码仍然可以正常运行降低维护成本:软件规模越大,寿命越长软件越长,软件的维护成本越高。最佳实践如果要做到“扩展开发,对修改封闭”,需要注意以下几点:时刻要有扩展、抽象、包装的意识,多花时间设计代码结构,把扩展点保持在advance大多数经典的设计模式都是为了解决代码扩展性的问题而总结出来的。开闭原则是对它们的重要评价。根据里式替换原则,里式替换原则的描述是,子类对象可以替换程序中父类对象出现的任何地方,并保证原程序的逻辑行为不变并且正确性没有被破坏。从代码实现的角度来看,面向对象多态与里式替换原理有些相似,但它们的侧重点不同:里式替换原理用于指导子类在继承关系中如何设计,以及子类的设计必须保证在替换父类时,不改变原程序的逻辑,不破坏原程序的正确性。优点遵循李式替换原则,会有以下优点:实现有意义的继承:保证父类的可重用性,减少系统错误故障,防止误用,不会破坏继承机制增强程序的健壮性:不同的子类可以完成不同的业务逻辑,即使添加子类也能保持很好的兼容性声明要实现的功能,比如把加法改成减法,子类违反了父类对输入、输出、异常的约定,子类如果相同情况下抛出的异常不同,则违反父类注释中列出的任何特殊声明接口隔离原则理解接口隔离原则的描述是不应强制接口的调用者或用户依赖于它的接口不需要。通过对接口的不同理解,接口隔离的原则有以下三种理解:1、如果把“接口”理解为一组接口,它可以是某个微服务的接口,也可以是某个类库的接口。如果某些接口仅供某些调用者使用,则需要将这些接口隔离并由这些调用者单独使用,而不要强制其他调用者依赖其他不会使用的接口。2、如果把“接口”理解为一个单一的API接口或函数,一些调用者只需要其中的一些函数,这个函数就需要拆分成多个更细粒度的函数,让调用者只依赖它的一个需要细粒度的功能。3、如果把“接口”理解为OOP中的接口,也可以理解为面向对象编程语言中的接口语法,那么接口的设计要尽可能简单,实现类和调用者接口的不应该依赖不必要的接口函数。接口隔离原则有点类似于单一职责原则,但是接口隔离原则更侧重于接口的设计,通常通过调用者如何使用接口来定义接口的设计是否足够单一职责。优点遵循接口隔离原则,会有以下优点:高内聚、低耦合:拆分成更细粒度的接口,减少外部交互,防止外部变更,提高系统的灵活性和可维护性可读性高性能易维护:合理的接口拆分粒度可以保证系统的稳定性,减少项目工程的代码冗余。受到限制。定义太小,会造成接口过多,设计复杂;如果定义太大,灵活性会降低。每个项目和产品都选择了环境因素。不同的环境对接口拆分有不同的标准。深入理解业务逻辑依赖倒置原理理解依赖倒置原理也叫依赖倒置原理。它的含义是:高层模块不应该依赖低层模块,高层模块和低层模块应该通过抽象相互依赖;抽象不应该依赖于具体的实现细节,而具体的实现细节依赖于抽象。Tomcat是用于运行JavaWeb应用程序的容器。编写好的Web应用代码只需要部署在Tomcat容器中,就可以被Tomcat容器调用执行。这里,Tomcat容器是高层模块,Web应用是低层模块。Tomcat容器和Web应用程序没有直接依赖关系,而是通过Servlet规范相互依赖,Servlet规范不依赖于具体的实现细节,但是Tomcat和Web应用程序依赖于Servlet规范。控制反转(InversionOfControl,IoC)是指将程序员自己对程序执行流程的控制反转到通过框架来控制。控制反转不是一种具体的设计技术,而是一种通用的设计思想,一般用来指导框架层面的设计。实现控制反转主要有两种方式:依赖注入和依赖查找。两者的区别在于前者是被动的接收对象。依赖的B对象是在类A的实例创建过程中创建的,不同的对象根据类型或名称注入不同的属性,而后者是主动的。请求对应类型对象和获取依赖对象的时间也可以在代码中自由控制。依赖注入依赖注入(DependencyInjection,DI)是一种具体的编码技术。详细总结就是:不在类内部通过new创建依赖对象,而是在外部创建依赖类对象后,通过构造函数、函数参数等方式传递(或注入)到类中。一个简单的依赖注册代码示例如下:packagecn.fatedeity.designpattern.philosophy;/***依赖注册示例*/publicclassDependencyInjectionCase{privateMessageSendermessageSender;publicDependencyInjectionCase(MessageSendermessageSender){this.messageSender=messageSender;}publicvoidsendMessage(Stringphone,Stringmessage){this.messageSender.send(phone,message);}publicstaticvoidmain(String[]args){MessageSendersmsSender=newSmsSender();DependencyInjectionCasedependencyInjectionCase0=newDependencyInjectionCase(smsSender);//SmsSendersms发送短信dependencyInjectionCase0.sendMessage("sms","smsmessage");MessageSenderinboxSender=newInboxSender();DependencyInjectionCasedependencyInjectionCase1=newDependencyInjectionCase(smsSender);//SmsSender收件箱发送收件箱消息dependencyInjectionCase1.sendMessage("inbox",“收件箱消息”);}}类Inb??oxSender实现MessageSender{@Overridepublicvoidsend(Stringphone,Stringmessage){System.out.println("InboxSender"+phone+"send"+message);}}类SmsSender实现MessageSender{@Overridepublicvoidsend(Stringphone,Stringmessage){System.out.println("SmsSender"+phone+"send"+message);}}interfaceMessageSender{voidsend(Stringphone,Stringmessage);}优点遵循依赖倒置原则,会有以下优点:查询依赖与应用代码分离,工厂类和单例类的数量大大减少,代码层面更清晰无侵入,无需依赖容器的API,无需实现一些特殊接口的BestPractices通过依赖注入提供的扩展点,简单配置所有所需的类及其依赖,然后框架可以自动创建对象,管理对象生命周期,依赖注入等功能现成创建依赖注入的方法有很多,例如GoogleGuide,JavaSpring,PicoContainer,ButterflyContainer,ETC。