脚本宝典收集整理的这篇文章主要介绍了想学会SOLID原则,看这一篇文章就够了!,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
在我们日常工作中,代码写着写着就出现下列的一些臭味。但是还好我们有SOLID这把‘尺子’, 可以拿着它不断去衡量我们写的代码,除去代码臭味。这就是我们要学习SOLID原则的原因所在。
一个很好的例子:在我们封装request库时,我们需要实现以下4个方法.
class MyRequestClient:
def post(self):
pass
def get(self):
pass
def update(self):
pass
def delete(self):
pass
#上面的方法就是属于同一职责。 如何还有其他的方法,那么这个类就不符合单一职责原则。
#例增加以下方法:
def get_db_data(self):
pass
def to_object(self):
pass
首先我们来看一个违反OCP原则的例子。
#bad code
def circle_draw():
PRint(f"this is circle draw")
def square_draw():
print(f"this is square draw")
def draw_all_Shape(shaPEs):
for shape in shapes:
if shape == "circle":
circle_draw()
if shape == "square":
square_draw()
这段代码的问题是如果再有新的类型需要draw, 我们需要修改draw_all_shape
函数来适配新的类型。
我们定义了一个抽象类Shape, 子类Square和Circle继承Shape. 并且在子类中重写了父类的方法。函数draw_all_shape是绘制所有图形。
From typing import List
from abc import ABCMeta, abstractmethod
class Shape(metaclass=ABCMeta):
@abstractmethod
def draw(self):
pass
class Square(Shape):
def draw(self):
print(f"this is square draw")
class Circle(Shape):
def draw(self):
print(f"this is circle draw")
def draw_all_shape(shapes: List[Shape]):
for shape in shapes:
shape.draw()
我们定义了一个抽象类Shape, 子类Square
和Circle
继承Shape
. 并且在子类中重写了父类的方法。函数draw_all_shape
是绘制所有图形。
def circle_draw():
print(f"this is circle draw")
def square_draw():
print(f"this is square draw")
def draw_all_shape_by_function(data: Dict[str,Callable]):
for key,value in data.ITems():
value()
data = {
"circle": circle_draw,
"square": square_draw
}
draw_all_shape_by_function(data=data)
Shape
.无需修改shape
类和draw_all_shape
就可以实现三角形类的绘制。首先我们来看一段违法LSP的例子
from typing import Iterable
class User():
def __init__(self, user: str) -> None:
self.user = user
def disable(self) -> None:
print(f"{self.user} disable!")
class Admin(User):
def __init__(self, user: str = "Admin") -> None:
self.user = user
def disable(self):
raise "Admin do not disable!"
def delete_user(users: Iterable[User]):
for user in users:
user.disable()
当执行delete_user
时,就会抛出TypeError
错误,Admin
类中disable
方法违法了LSP替换原则。
#Good
from typing import Iterable
class User():
def __init__(self, user: str) -> None:
self.user = user
def allow_disable(self):
return True
def disable(self) -> None:
print(f"{self.user} disable!")
class Admin(User):
def __init__(self, user: str = "Admin") -> None:
self.user = user
def allow_disable(self):
return False
def delete_user(users: Iterable[User]) -> None:
for user in users:
if user.allow_disable:
user.disable()
allow_disable
的方法,解决了Admin类不能disable
的问题。首先看一个违反DIP原则的例子:
class Lamp:
def turn_on(self):
print("turn on the lamp")
def turn_off(self):
print("turn off the lamp")
class Button():
def __init__(self) -> None:
self.lamp = Lamp()
def turn_on(self):
return self.lamp.turn_on()
def turn_off(self):
return self.lamp.turn_off()
当有一天,button需要控制televsion时,就需要修改Button类。Button
和Lamp
具有强耦合关系。所以,当Lamp变动时,会影响到Button类。违法了DIP原则的高层模块依赖于底层模块。
定义一个抽象类ElectricAppliance
Button 和 Lamp 都依赖这个抽象类。 解决了Button
和Lamp
具有强耦合的问题。
class ElectricAppliance(metaclass=ABCMeta):
@abstractmethod
def turn_on(self):
pass
@abstractmethod
def turn_off(self):
pass
class Lamp(ElectricAppliance):
def turn_on(self):
print("turn on the lamp")
def turn_off(self):
print("turn off the lamp")
class Television(ElectricAppliance):
def turn_on(self):
print("turn on the televison")
def turn_off(self):
print("turn off the televison")
class Button:
def __init__(self, electric_appliance: ElectricAppliance) -> None:
self.electric_appliance = electric_appliance
def turn_on(self):
self.electric_appliance.turn_on()
def turn_off(self):
self.electric_appliance.turn_off()
首先来看一个违反ISP原则的例子:
class Animal(metaclass=ABCMeta):
@abstractclassmethod
def run(self):
pass
@abstractclassmethod
def speak(self):
pass
@abstractclassmethod
def fly(self):
pass
class Dog(Animal):
def run(self):
return "Dog Running"
def speak(self):
return "Dog Speaking"
def fly(self):
raise TypeError("Dog can not fly")
class Bird(Animal):
def run(self):
raise TypeError("Bird can not run")
def speak(self):
return "Bird Speaking"
def fly(self):
return "Bird fly"
def fly_animal(animals: Iterable[Animal]):
for animal in animals:
animal.fly()
@H_304_257@
当我们执行fly_animal
时,就会抛出TypeError
的错误。此时Animal抽象类是一个胖类,违法了ISP原则。
#good
class FlyingAnimal(metaclass=ABCMeta):
@abstractclassmethod
def fly(self):
pass
class RunningAnimal(metaclass=ABCMeta):
@abstractclassmethod
def run(self):
pass
class TalkingAnimal(metaclass=ABCMeta):
@abstractclassmethod
def talk(self):
pass
class Dog(RunningAnimal,TalkingAnimal):
def run(self):
return "Dog Running"
def talk(self):
return "Dog Speaking"
class Bird(FlyingAnimal, TalkingAnimal):
def talk(self):
return "Bird Speaking"
def fly(self):
return "Bird fly"
def fly_animal(animals: Iterable[FlyingAnimal]):
for animal in animals:
print(animal.fly())
以上是脚本宝典为你收集整理的想学会SOLID原则,看这一篇文章就够了!全部内容,希望文章能够帮你解决想学会SOLID原则,看这一篇文章就够了!所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。