QZQ的小世界!

  • 首页
你好!
这里是QZQ的博客站!
  1. 首页
  2. 未分类
  3. 正文

依赖倒置原则——Python案例理解

2024年12月25日 294点热度 0人点赞 0条评论

前言

自己在写一些工程的时候,发现各种模块要重写很多次,感觉自己“思路不清晰”…毕竟自己不是科班出身,实际干起活就感觉差点东西。

后来在网上学习的时候,发现了一些有关“面向对象编程的设计原则”的文章。小看一眼,感觉灵光一现,好东西!

然而网上大多数教程都是用Java来写的,这里就使用python来重写一下,顺便理理自己的思路。

定义

这里就照搬了:

1、上层模块不应该依赖底层模块,它们都应该依赖于抽象。

2、抽象不应该依赖于细节,细节应该依赖于抽象。

High level modules should not depend upon low level modules. Both should depend upon abstractions.Abstractions should not depend upon details. Details should depend upon abstractions.

什么是依赖

假设A类的变化引起了B类的变化,则说名B类依赖于A类。

浅显点的理解

按照上面的定义,抽象类应该是最大的,所有属性或者实例的变更,都不能去影响这个抽象类。写代码的时候,各种类应该由抽象类派生出来,然后依照抽象类对其进行再加工或者是继承之类的。

一个案例

先看把目光看向一个披萨店,按照我们在现实中的思维来想:先有披萨店,然后才有顾客来买披萨,然后由披萨店产出了披萨,大概如下图所示:

图中解释的会有些抽象,具体来说是这样:

因为是由披萨店产出的披萨,披萨归属于披萨店所有,也就是说披萨是披萨店的一部分。那么按照“假设A类的变化引起了B类的变化,则说名B类依赖于A类”的原则,披萨的变动就是披萨店的变动。

这种设计放在编程中就比较戏剧性了,负责设计披萨的程序员新增一种披萨,结果披萨店要因此装修改动一番?!

因此就出现了“依赖倒置原则”,在本案例中,如果按照本原则进行设计,呈现的效果会如下图所示:

按照定义里的话来解释,披萨是一种“抽象”,各种各样的披萨由该抽象类衍生。比如定义了个抽象披萨类,有两个具体属性:下层面饼,上层食料。其他的披萨,比如芝士披萨,海鲜披萨,都需要实现下层面饼,和上层食料各是什么样的。

而披萨店这个类,实现一个出“抽象”披萨的方法,这样一来由披萨设计程序员设计的任何披萨类,都能直接由披萨店产出,而无需对披萨店进行任何改动。

Python代码实现

如果按照现实思路来设计代码的话,代码如下所示

class PizzaStore:
    def __init__(self):
        # 按照我们的想法先设计一个披萨店
        print('披萨店构建完成咯')
        self.store = []  # 假设这是一个餐车吧,做完餐就加入这个列表

    def _make_CheesePizza(self):
        # 私有方法,制作一个CheesePizza,不让外部调用
        self.store.append(CheesePizza())

    def order_CheesePizza(self):
        self._make_CheesePizza()  # 接到点单,启动做披萨函数,餐车披萨+1
        return self.store.pop()  # 然后从餐车弹出披萨给顾客

    def _make_SeafoodPizza(self):
        # 可以看出每新增一个披萨种类,都要设计一组新函数
        self.store.append(SeafoodPizza())

    def order_SeafoodPizza(self):
        self._make_SeafoodPizza()
        return self.store.pop()


class CheesePizza:
    def __init__(self):
        self.name = '芝士披萨'
        print('做出了个 芝士披萨')


class SeafoodPizza:
    def __init__(self):
        self.name = '海鲜披萨'
        print('做出了个 海鲜披萨')


if __name__ == '__main__':
    # 先出现个披萨店
    pizza_store = PizzaStore()
    pizza = pizza_store.order_CheesePizza()
    print(f'拿到手的是{pizza.name}')
    pizza = pizza_store.order_SeafoodPizza()
    print(f'拿到手的是{pizza.name}')

 

上述代码运行结果如下

披萨店构建完成咯
做出了个 芝士披萨
拿到手的是芝士披萨
做出了个 海鲜披萨
拿到手的是海鲜披萨

 

很显然这样设计披萨店实在是太繁琐了,维护成本炸裂。所以运用依赖倒置原则:

from abc import ABC, abstractmethod  #


class Pizza(ABC):
    # Pizza继承了ABC(Abstract Class),成为了抽象类,任何继承该类的子类都应该实现对应的方法
    def __init__(self):
        pass

    @abstractmethod
    def get_name(self) -> str:
        # 这里就简单点,任何披萨都应该有一个名字,将其返回
        pass


class CheesePizza(Pizza):
    def __init__(self):
        super().__init__()
        self.name = '芝士披萨'
        print(f'做出了个 {self.name}')

    def get_name(self) -> str:
        return self.name


class SeafoodPizza(Pizza):
    def __init__(self):
        super().__init__()
        self.name = '海鲜披萨'
        print(f'做出了个 {self.name}')

    def get_name(self) -> str:
        return self.name


class PizzaStore:
    def __init__(self, menu):
        # 先有了披萨,那根据披萨这个抽象类设计整个PizzaStore的架构
        # 由于不能依赖具体的披萨的披萨架构,因此披萨店就根据一份菜单来进行披萨的生产,menu是一个字典
        print('披萨店构建完成咯')
        self.menu = menu

    def _make_pizza(self, pizza_name):
        # 私有方法,按照菜单,制作一个Pizza
        return self.menu[pizza_name]()  # 这里加括号是要将其实例化

    def order_pizza(self, pizza_name):
        return self._make_pizza(pizza_name)


if __name__ == '__main__':
    # 根据现有的披萨设计一份菜单
    my_menu = {'芝士披萨': CheesePizza, '海鲜披萨': SeafoodPizza}
    # 出现披萨店,披萨店的运营需要一份菜单
    pizza_store = PizzaStore(my_menu)

    # 开始点单
    pizza = pizza_store.order_pizza('海鲜披萨')
    print(f'拿到手的是{pizza.get_name()}')

 

上述代码运行后的结果就是

披萨店构建完成咯
做出了个 海鲜披萨
拿到手的是海鲜披萨

 

显然可维护性高了不少。

参考

《设计模式》——依赖倒置原则 - 简书

六大设计原则之依赖倒置原则(DIP) - 简书

面向对象编程的六大原则

最少知识原则——Python案例理解 - QZQ的小世界!

开放封闭原则——Python案例理解 - QZQ的小世界!

里氏替换原则——Python案例理解 - QZQ的小世界!

依赖倒置原则——Python案例理解 - QZQ的小世界!

单一职责原则——Python案例理解 - QZQ的小世界!

接口分离原则——Python案例理解 - QZQ的小世界!

本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2025年3月12日

QZQ

一只涉猎广泛的技术爱好者,绝赞养猫中~

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

归档

  • 2025 年 4 月
  • 2025 年 3 月
  • 2025 年 2 月
  • 2025 年 1 月
  • 2024 年 12 月
  • 2024 年 11 月

分类

  • 技术
  • 未分类

COPYRIGHT © 2024 QZQ的小世界!. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang