一.定义
依赖倒置原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
即:层次的模块不应该依赖于低层次的模块,它们都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象
目的:依赖倒置原则的目的是通过要面向接口的编程来降低类间的耦合性~
二.原理
在设计软件时,应该将高层模块与低层模块之间的依赖关系进行颠倒。具体来说,高层模块不应该依赖于低层模块的细节实现,而应该依赖于抽象接口。这样的设计使得系统更加灵活和易于扩展,减少了模块间的耦合,使得代码更加稳定和易于测试。
总结起来,依赖倒置原则是面向对象设计中的重要原则,通过将高层模块依赖于抽象接口,而不是低层模块的细节实现,能够实现松耦合的组件和更易于测试的代码。
三.引例
例1:在一个电商系统中,可能需要支持多种支付方式(如支付宝、微信、银行卡等)。通过定义一个抽象的支付接口,高层模块可以依赖于这个接口,而不是具体的支付实现。这样,当需要添加新的支付方式时,只需实现一个新的支付类,而无需修改高层模块的代码~
例2:在一个通知系统中,可能需要通过不同的方式(如邮件、短信、推送等)发送消息。通过定义一个抽象的消息发送接口,高层模块可以依赖于这个接口,而不是具体的消息发送实现。这样,当需要添加新的消息发送方式时,只需实现一个新的消息发送类,而无需修改高层模块的代码。
例3:数据读取:在一个系统中,可能需要从不同的数据源(如文件、数据库、网络等)读取数据。通过定义一个抽象的数据读取接口,高层模块可以依赖于这个接口,而不是具体的数据读取实现。这样,当需要添加新的数据读取方式时,只需实现一个新的数据读取类,而无需修改高层模块的代码。
例4:还是足球运动员的例子,在国家队招收球员时,可以从各国联赛(英法德西意)招募人员。通过建立一个专门的部门来负责,则总部可以从这里直接招收人,而不需要辗转各地发球星~这样,当有新的联赛崛起时(比甲、荷甲),只需要向专门的部门提供信息,而无需直接对接总部~
例5:假设我们有一个订单处理系统,其中包含订单类
Order
和邮件通知类EmailNotification
,邮件通知类负责向客户发送订单确认邮件。传统的设计方式是在订单类中直接创建邮件通知类的实例来发送邮件通知,但这样的设计违背了依赖倒置原则。下面是传统的设计方式:
class Order: def __init__(self, order_id, customer_name): self.order_id = order_id self.customer_name = customer_name self.email_notification = EmailNotification() def process(self): # 处理订单逻辑 # 发送订单确认邮件 self.email_notification.send_notification(self.customer_name)
在这个传统的设计中,订单类直接依赖于具体的邮件通知类
EmailNotification
,这样的设计使得订单类与邮件通知类紧密耦合,增加了代码的依赖性和可测试性。而符合依赖倒置原则的设计方式是通过依赖注入来解耦:
class Order: def __init__(self, order_id, customer_name, notification_service): self.order_id = order_id self.customer_name = customer_name self.notification_service = notification_service def process(self): # 处理订单逻辑 # 发送订单确认邮件 self.notification_service.send_notification(self.customer_name)
在这个设计中,订单类通过构造函数接收一个抽象的通知服务
notification_service
,而不是直接创建具体的邮件通知类实例。这样的设计使得订单类与具体的邮件通知类解耦,提高了代码的灵活性和可测试性。代码解析: 通过上述示例代码,我们可以看到传统的设计方式在订单类中直接创建了具体的邮件通知类实例,使得订单类与邮件通知类紧密耦合。而符合依赖倒置原则的设计方式通过依赖注入来解耦,使得订单类依赖于抽象的通知服务,而不依赖于具体的邮件通知类。这样的设计使得代码更加灵活、易于扩展和维护。