前端开发工程师、技术日更博主、已过CET6 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》蓝桥云课签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》文章目录一、单一职责原则Single Responsibility Principle1.1 定义1.2 优点1.3 示例二、开闭原则Open/Closed Principle2.1 定义2.2 优点2.3 示例三、里氏替换原则Liskov Substitution Principle3.1 定义3.2 优点3.3 示例四、依赖倒置原则Dependency Inversion Principle4.1 定义4.2 优点4.3 示例五、接口分离原则Interface Segregation Principle5.1 定义5.2 优点5.3 示例六、迪米特法则Law of Demeter6.1 定义6.2 优点6.3 示例七、总结设计模式是软件工程中用于解决常见问题的可复用解决方案。它们不仅提供了经过验证的解决方案还遵循一系列设计原则这些原则有助于编写出更可维护、可扩展和灵活的代码。本文将详细介绍设计模式的六大原则单一职责原则、开闭原则、里氏替换原则、依赖倒置原则、接口分离原则和迪米特法则并探讨它们在实际开发中的应用。一、单一职责原则Single Responsibility Principle1.1 定义单一职责原则指出一个类应该只有一个发生变化的原因。如果一个类负责多个功能那么它可能会因为其中一个功能的变更而需要修改从而影响到其他功能。1.2 优点降低类的复杂度类的职责单一结构清晰易于理解和维护。提高类的可复用性单一职责的类更有可能被复用因为它们更通用。降低变更风险一个类只负责一个功能变更一个功能不会影响到其他功能。1.3 示例classUser:def__init__(self,name,email):self.namename self.emailemaildefsave(self):# 保存用户到数据库passclassUserDatabase:defsave(self,user):# 保存用户到数据库pass在上述代码中User类只负责用户数据的封装而UserDatabase类负责用户数据的持久化。这样每个类都有单一的职责符合单一职责原则。二、开闭原则Open/Closed Principle2.1 定义开闭原则指出软件实体应该对扩展开放对修改关闭。这意味着在不修改现有代码的情况下可以通过添加新的代码来扩展功能。2.2 优点减少对现有代码的修改降低引入新错误的风险。提高系统的可扩展性可以通过添加新的代码来扩展功能而不需要修改现有代码。2.3 示例classShape:defdraw(self):passclassCircle(Shape):defdraw(self):print(Drawing a circle)classSquare(Shape):defdraw(self):print(Drawing a square)defdraw_shapes(shapes):forshapeinshapes:shape.draw()# 添加新的形状classTriangle(Shape):defdraw(self):print(Drawing a triangle)shapes[Circle(),Square(),Triangle()]draw_shapes(shapes)在上述代码中通过继承Shape类并实现draw方法可以添加新的形状而不需要修改draw_shapes函数。这符合开闭原则。三、里氏替换原则Liskov Substitution Principle3.1 定义里氏替换原则指出子类对象必须能够替换掉它们的父类对象并且不破坏系统的正确性。这意味着子类对象必须完全兼容父类对象的行为。3.2 优点增强系统的可扩展性子类可以无缝替换父类而不会影响系统的其他部分。提高代码的可维护性子类的行为与父类一致便于理解和维护。3.3 示例classBird:deffly(self):passclassSparrow(Bird):deffly(self):print(Sparrow flying)classOstrich(Bird):deffly(self):raiseNotImplementedError(Ostriches cannot fly)defmake_bird_fly(bird):bird.fly()sparrowSparrow()ostrichOstrich()make_bird_fly(sparrow)# 输出Sparrow flyingmake_bird_fly(ostrich)# 抛出异常在上述代码中Ostrich类继承自Bird类但Ostrich不能飞行这违反了里氏替换原则。正确的做法是重新设计类结构避免这种不兼容的行为。四、依赖倒置原则Dependency Inversion Principle4.1 定义依赖倒置原则指出高层模块不应该依赖于低层模块二者都应该依赖于抽象。抽象不应该依赖于细节细节应该依赖于抽象。4.2 优点降低模块间的耦合度高层模块和低层模块通过抽象接口通信降低了直接依赖。提高系统的可维护性通过抽象接口可以更容易地替换低层模块的实现。4.3 示例# 高层模块classApplication:def__init__(self,database):self.databasedatabasedefrun(self):self.database.connect()self.database.query(SELECT * FROM users)# 低层模块classDatabase:defconnect(self):passdefquery(self,query):pass# 抽象接口classDatabaseInterface:defconnect(self):passdefquery(self,query):pass# 低层模块实现classMySQLDatabase(DatabaseInterface):defconnect(self):print(Connecting to MySQL database)defquery(self,query):print(fExecuting query:{query})# 高层模块依赖抽象接口classApplication:def__init__(self,database:DatabaseInterface):self.databasedatabasedefrun(self):self.database.connect()self.database.query(SELECT * FROM users)# 使用appApplication(MySQLDatabase())app.run()在上述代码中Application类依赖于DatabaseInterface抽象接口而不是具体的MySQLDatabase类。这符合依赖倒置原则。五、接口分离原则Interface Segregation Principle5.1 定义接口分离原则指出不应该强迫客户依赖于它们不使用的方法。一个类对另一个类的依赖应该建立在最小的接口上。5.2 优点减少不必要的依赖客户端只依赖于它们需要的方法减少了不必要的依赖。提高系统的灵活性通过分离接口可以更容易地扩展和修改系统。5.3 示例# 错误大而全的接口classMachine:defprint(self,document):passdeffax(self,document):passdefscan(self,document):pass# 正确分离接口classPrinter:defprint(self,document):passclassFaxMachine:deffax(self,document):passclassScanner:defscan(self,document):pass# 组合使用classMultiFunctionPrinter(Printer,FaxMachine,Scanner):pass# 使用printerPrinter()printer.print(document)fax_machineFaxMachine()fax_machine.fax(document)在上述代码中MultiFunctionPrinter类组合了Printer、FaxMachine和Scanner接口而不是实现一个大而全的接口。这符合接口分离原则。六、迪米特法则Law of Demeter6.1 定义迪米特法则指出一个对象应该对其他对象有尽可能少的了解。一个类应该只与它的直接朋友通信而不是与朋友的朋友通信。6.2 优点降低耦合度减少类之间的直接依赖降低耦合度。提高系统的可维护性通过减少类之间的直接依赖可以更容易地修改和扩展系统。6.3 示例# 错误违反迪米特法则classDepartment:def__init__(self,name):self.namenameclassEmployee:def__init__(self,name,department):self.namename self.departmentdepartmentdefget_department_name(self):returnself.department.name# 正确遵循迪米特法则classDepartment:def__init__(self,name):self.namenameclassEmployee:def__init__(self,name,department):self.namename self.departmentdepartmentdefget_department_name(self):returnself.department.get_name()classDepartment:def__init__(self,name):self.namenamedefget_name(self):returnself.name# 使用departmentDepartment(Engineering)employeeEmployee(John Doe,department)print(employee.get_department_name())# 输出Engineering在上述代码中Employee类通过department.get_name()获取部门名称而不是直接访问department.name。这符合迪米特法则。七、总结设计模式的六大原则是编写高质量代码的重要指导思想。通过遵循这些原则可以设计出更可维护、可扩展和灵活的系统。在实际开发中应根据具体需求合理应用这些原则避免过度设计。通过本文的介绍希望读者能够对设计模式的六大原则有更清晰的理解并在实际开发中应用这些原则来提高代码质量。