资讯动态

面向对象设计原则:SOLID原则详解

发布时间:2026/10/23 2:06:46 来源:尧图企业网站定制
在面向对象编程的世界里想要编写出高质量、易维护的代码遵循一些设计原则是非常重要的。今天我们要详细讲解的SOLID原则就是这样一组至关重要的设计原则。它就像是我们在编写代码时的指南针能帮助我们避免很多代码可维护性差的问题让我们的代码更加健壮和灵活。接下来我们就一起深入了解SOLID原则的含义、作用并且通过Python代码示例看看违反和遵循这些原则的代码有什么不同。目录SOLID原则概述单一职责原则Single Responsibility Principle含义和作用代码示例开闭原则Open/Closed Principle含义和作用代码示例里氏替换原则Liskov Substitution Principle含义和作用代码示例接口隔离原则Interface Segregation Principle含义和作用代码示例依赖倒置原则Dependency Inversion Principle含义和作用代码示例总结 系列专栏导航SOLID原则概述SOLID原则是由罗伯特·C·马丁Robert C. Martin在21世纪早期引入的它包含了五个面向对象设计的原则这五个原则首字母组合起来就是SOLID分别是单一职责原则Single Responsibility Principle、开闭原则Open/Closed Principle、里氏替换原则Liskov Substitution Principle、接口隔离原则Interface Segregation Principle和依赖倒置原则Dependency Inversion Principle。这些原则旨在提高软件的可维护性、可扩展性和可复用性。单一职责原则Single Responsibility Principle含义和作用单一职责原则简单来说就是一个类应该只有一个引起它变化的原因。这就好比一个人只负责一项工作这样当这项工作发生变化时只需要这个人做出调整而不会影响到其他工作。在代码中遵循单一职责原则可以让类的功能更加聚焦降低类之间的耦合度提高代码的可维护性。代码示例违反单一职责原则的代码classUserService:defcreate_user(self,username,password):# 创建用户逻辑print(fCreating user{username}with password{password})defsend_welcome_email(self,username,email):# 发送欢迎邮件逻辑print(fSending welcome email to{email}for user{username})# 使用示例user_serviceUserService()user_service.create_user(john_doe,123456)user_service.send_welcome_email(john_doe,johnexample.com)在这个例子中UserService类承担了两个职责创建用户和发送欢迎邮件。如果发送欢迎邮件的逻辑发生变化比如邮件模板需要修改那么就可能会影响到创建用户的功能这违反了单一职责原则。遵循单一职责原则的代码classUserCreator:defcreate_user(self,username,password):# 创建用户逻辑print(fCreating user{username}with password{password})classWelcomeEmailSender:defsend_welcome_email(self,username,email):# 发送欢迎邮件逻辑print(fSending welcome email to{email}for user{username})# 使用示例user_creatorUserCreator()user_creator.create_user(john_doe,123456)email_senderWelcomeEmailSender()email_sender.send_welcome_email(john_doe,johnexample.com)这里我们将创建用户和发送欢迎邮件的职责分别封装到了UserCreator和WelcomeEmailSender两个类中这样每个类只负责一项职责当其中一个职责发生变化时不会影响到另一个职责。开闭原则Open/Closed Principle含义和作用开闭原则指的是软件实体类、模块、函数等应该对扩展开放对修改关闭。也就是说当需要增加新功能时我们应该通过扩展现有代码来实现而不是直接修改已有的代码。这样可以保证代码的稳定性避免因为修改现有代码而引入新的错误。代码示例违反开闭原则的代码classShape:def__init__(self,shape_type):self.shape_typeshape_typedefcalculate_area(self):ifself.shape_typecircle:# 计算圆形面积radius5return3.14*radius*radiuselifself.shape_typerectangle:# 计算矩形面积length10width5returnlength*width# 使用示例circleShape(circle)print(circle.calculate_area())rectangleShape(rectangle)print(rectangle.calculate_area())在这个例子中如果我们需要增加一种新的形状比如三角形就需要修改calculate_area方法这违反了开闭原则。遵循开闭原则的代码fromabcimportABC,abstractmethodclassShape(ABC):abstractmethoddefcalculate_area(self):passclassCircle(Shape):def__init__(self,radius):self.radiusradiusdefcalculate_area(self):return3.14*self.radius*self.radiusclassRectangle(Shape):def__init__(self,length,width):self.lengthlength self.widthwidthdefcalculate_area(self):returnself.length*self.width# 使用示例circleCircle(5)print(circle.calculate_area())rectangleRectangle(10,5)print(rectangle.calculate_area())这里我们使用抽象基类Shape定义了一个抽象方法calculate_area每个具体的形状类如Circle和Rectangle都继承自Shape并实现了calculate_area方法。当需要增加新的形状时我们只需要创建一个新的类继承自Shape并实现calculate_area方法而不需要修改现有的代码。里氏替换原则Liskov Substitution Principle含义和作用里氏替换原则是指子类可以替换其父类并且不会影响程序的正确性。也就是说子类应该能够完全替代父类并且程序的行为不会发生改变。这有助于保证代码的可复用性和可扩展性。代码示例违反里氏替换原则的代码classRectangle:def__init__(self,width,height):self.widthwidth self.heightheightdefset_width(self,width):self.widthwidthdefset_height(self,height):self.heightheightdefget_area(self):returnself.width*self.heightclassSquare(Rectangle):defset_width(self,width):self.widthwidth self.heightwidthdefset_height(self,height):self.heightheight self.widthheight# 使用示例rectangleRectangle(10,5)print(rectangle.get_area())squareSquare()square.set_width(5)print(square.get_area())在这个例子中Square类继承自Rectangle类但是Square类的set_width和set_height方法改变了Rectangle类的行为因为正方形的边长是相等的。如果在代码中用Square类替换Rectangle类可能会导致程序的行为不符合预期这违反了里氏替换原则。遵循里氏替换原则的代码fromabcimportABC,abstractmethodclassShape(ABC):abstractmethoddefget_area(self):passclassRectangle(Shape):def__init__(self,width,height):self.widthwidth self.heightheightdefget_area(self):returnself.width*self.heightclassSquare(Shape):def__init__(self,side):self.sidesidedefget_area(self):returnself.side*self.side# 使用示例rectangleRectangle(10,5)print(rectangle.get_area())squareSquare(5)print(square.get_area())这里我们通过抽象基类Shape来定义一个抽象方法get_areaRectangle和Square类都继承自Shape并实现了get_area方法。这样Rectangle和Square类都可以作为Shape类的子类使用而不会影响程序的正确性。接口隔离原则Interface Segregation Principle含义和作用接口隔离原则是指客户端不应该依赖它不需要的接口。也就是说一个类对另一个类的依赖应该建立在最小的接口上。这样可以避免类依赖一些不必要的方法降低类之间的耦合度。代码示例违反接口隔离原则的代码fromabcimportABC,abstractmethodclassWorkerInterface(ABC):abstractmethoddefwork(self):passabstractmethoddefeat(self):passclassWorker(WorkerInterface):defwork(self):print(Working...)defeat(self):print(Eating...)classRobot(WorkerInterface):defwork(self):print(Robot working...)defeat(self):# 机器人不需要吃东西这里的实现没有意义pass# 使用示例workerWorker()worker.work()worker.eat()robotRobot()robot.work()在这个例子中WorkerInterface定义了work和eat两个方法但是Robot类并不需要eat方法这就导致Robot类依赖了它不需要的接口违反了接口隔离原则。遵循接口隔离原则的代码fromabcimportABC,abstractmethodclassWorkable(ABC):abstractmethoddefwork(self):passclassEatable(ABC):abstractmethoddefeat(self):passclassWorker(Workable,Eatable):defwork(self):print(Working...)defeat(self):print(Eating...)classRobot(Workable):defwork(self):print(Robot working...)# 使用示例workerWorker()worker.work()worker.eat()robotRobot()robot.work()这里我们将WorkerInterface拆分成了Workable和Eatable两个接口Worker类实现了这两个接口而Robot类只实现了Workable接口这样每个类只依赖它需要的接口符合接口隔离原则。依赖倒置原则Dependency Inversion Principle含义和作用依赖倒置原则强调高层模块不应该依赖低层模块二者都应该依赖抽象。抽象不应该依赖细节细节应该依赖抽象。简单来说就是要依赖接口或抽象类而不是具体的实现类。这样可以降低类之间的耦合度提高代码的可维护性和可扩展性。代码示例违反依赖倒置原则的代码classLightBulb:defturn_on(self):print(Light bulb is on)defturn_off(self):print(Light bulb is off)classSwitch:def__init__(self):self.light_bulbLightBulb()defoperate(self):self.light_bulb.turn_on()# 使用示例switchSwitch()switch.operate()在这个例子中Switch类直接依赖了LightBulb类这就导致Switch类和LightBulb类之间的耦合度很高。如果我们想要更换另一种类型的灯泡就需要修改Switch类的代码。遵循依赖倒置原则的代码fromabcimportABC,abstractmethodclassSwitchable(ABC):abstractmethoddefturn_on(self):passabstractmethoddefturn_off(self):passclassLightBulb(Switchable):defturn_on(self):print(Light bulb is on)defturn_off(self):print(Light bulb is off)classSwitch:def__init__(self,device):self.devicedevicedefoperate(self):self.device.turn_on()# 使用示例light_bulbLightBulb()switchSwitch(light_bulb)switch.operate()这里我们定义了一个抽象基类SwitchableLightBulb类实现了Switchable接口。Switch类依赖的是Switchable接口而不是具体的LightBulb类。这样当我们需要更换另一种类型的设备时只需要创建一个新的类实现Switchable接口然后将其传递给Switch类即可不需要修改Switch类的代码。总结通过以上对SOLID原则的详细讲解和代码示例我们了解了每个原则的含义、作用以及违反和遵循这些原则的代码区别。遵循SOLID原则可以帮助我们编写出高质量、易维护的代码避免在开发中因为违反设计原则而导致代码可维护性差的问题。掌握了SOLID原则的内容后下一节我们将深入学习设计模式的具体类型进一步完善对本章设计模式基础主题的认知。 系列专栏导航 《深入浅出设计模式》 JDK5新特性 JDK8新特性 JDK11新特性 JDK17新特性 JDK21新特性 全面掌握MySQL工具建议按系列顺序阅读从基础到进阶逐步掌握核心能力避免遗漏关键知识点其他专栏衔接 《若依框架全攻略从入门到项目实战》 《深入浅出Mybatis》 《全面掌握Swagger从入门到实战》 《Lombok高效Java开发的秘密武器完全解读》 博客概览《程序员技术成长导航专栏汇总》

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑