Bob*_*lds 8 python oop dependency-injection python-3.x solid-principles
我已经开始将SOLID 原则应用到我的项目中。所有这些对我来说都很清楚,除了依赖倒置,因为在 Python 中,我们没有改变在另一个类中定义某个类的类型的变量(或者可能只是我不知道)。所以我以两种形式实现了依赖倒置原则,想知道哪一种是正确的,我该如何纠正它们。这是我的代码:
d1.py:
class IFood:
def bake(self, isTendir: bool): pass
class Production:
def __init__(self):
self.food = IFood()
def produce(self):
self.food.bake(True)
class Bread(IFood):
def bake(self, isTendir:bool):
print("Bread was baked")
Run Code Online (Sandbox Code Playgroud)
d2.py:
from abc import ABC, abstractmethod
class Food(ABC):
@abstractmethod
def bake(self, isTendir): pass
class Production():
def __init__(self):
self.bread = Bread()
def produce(self):
self.bread.bake(True)
class Bread(Food):
def bake(self, isTendir:bool):
print("Bread was baked")
Run Code Online (Sandbox Code Playgroud)
CRI*_*SPR 76
Robert C. Martin\xe2\x80\x99 对依赖倒置原理的定义\n由两部分组成:
\n\n\n\n
\n- 高层模块不应该依赖于低层模块。两者都应该依赖于抽象。
\n- 抽象不应该依赖于细节。细节应该取决于抽象。
\n
只是为了澄清......一个模块可以是一个函数、一个类、一个文件...一段代码。
\n假设您有一个程序需要您烤面包。
\n在更高的层面上,有一个点你可以调用cook()
实现这一点的一个糟糕方法是创建一个既做饭又创建面包的函数。
\ndef cook():\n bread = Bread()\n bread.bake()\n\ncook()\nRun Code Online (Sandbox Code Playgroud)\n不是很好...
\n如您所见,该cook函数取决于Bread.
那么如果你想烤饼干怎么办?
\n菜鸟错误是添加一个字符串参数,如下所示:
\ndef cook(food: str):\n if food == "bread":\n bread = Bread()\n bread.bake()\n if food == "cookies":\n cookies = Cookies()\n cookies.bake()\n\ncook("cookies")\nRun Code Online (Sandbox Code Playgroud)\n这显然是错误的。因为通过添加更多食物,您会更改代码,并且代码会因许多 if 语句而变得混乱。它几乎打破了所有原则。
\n因此,您需要的cook功能是较高级别的模块,而不是依赖于较低级别的模块,例如Bread或Cookies
所以我们唯一需要的是我们可以烘烤的东西。我们会烘烤它。现在正确的方法是实现一个接口。在 Python 中,这不是必需的,但强烈建议保持代码整洁且面向未来!
\n\n\n如果它看起来像鸭子,游泳像鸭子,嘎嘎叫像鸭子,那么它可能就是鸭子。
\n
他们说。
\n现在让我们反转依赖关系!
\nfrom abc import ABC, abstractmethod\nclass Bakable(ABC):\n @abstractmethod\n def bake(self):\n pass\n\ndef cook(bakable:Bakable):\n bakable.bake()\nRun Code Online (Sandbox Code Playgroud)\n现在cook功能取决于抽象。 不是在面包上,不是在饼干上,而是在抽象上。现在任何任何都Bakable可以烘烤。
通过实现该接口,我们确信每个接口Bakable都会有一个bake()执行某些操作的方法。
但现在cook函数不需要知道。\ncook 函数将烘焙任何Bakable.
依赖关系现在转到客户端。客户是想要烘焙一些东西的人。客户端是一段将要使用cook函数的代码。客户知道要烘烤什么。
现在通过查看该cook函数,客户端知道该cook函数等待接收Bakable并且只接收一个Bakable。
那么让我们来制作一些面包吧。
\nclass Bread(Bakable):\n def bake(self):\n print('Smells like bread')\nRun Code Online (Sandbox Code Playgroud)\n现在让我们创建一些cookie!
\nclass Cookies(Bakable):\n def bake(self):\n print('Cookie smell all over the place')\nRun Code Online (Sandbox Code Playgroud)\n好的!现在我们来煮它们。
\ncookies = Cookies()\nbread = Bread()\ncook(cookies)\ncook(bread)\nRun Code Online (Sandbox Code Playgroud)\n
Nik*_* M. 12
# define a common interface any food should have and implement
class IFood:
def bake(self): pass
def eat(self): pass
class Bread(IFood):
def bake(self):
print("Bread was baked")
def eat(self):
print("Bread was eaten")
class Pastry(IFood):
def bake(self):
print("Pastry was baked")
def eat(self):
print("Pastry was eaten")
class Production:
def __init__(self, food): # food now is any concrete implementation of IFood
self.food = food # this is also dependnecy injection, as it is a parameter not hardcoded
def produce(self):
self.food.bake() # uses only the common interface
def consume(self):
self.food.eat() # uses only the common interface
Run Code Online (Sandbox Code Playgroud)
用它:
ProduceBread = Production(Bread())
ProducePastry = Production(Pastry())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3058 次 |
| 最近记录: |