面向对象设计SOLID原则¶
不积跬步无以至千里,不积小流无以成江海。
Author: 李东阳
1.开放封闭原则¶
一个软件实体,如类、模块、函数因该对扩张开发,对修改关闭。即软件实体应该尽量在不修改原来的代码的前提下进行扩展。
2.里氏替换原则¶
所有引用父类的地方必须能够透明地使用其子类的东西。
简单来说就是,将一个父类的对象传入一个函数。那么必须支持这个父类的子类对象也可以传入。
举个例子:
有一个函数是用来显示用户的信息,那么传入一个普通用户进去没有问题,就应该做到传入VIP用户也没有问题。(注:VIP用户是普通用户的子类)
class User:
def show_info(self):
pass
class VIPUser(User):
def show_info(self):
pass
def show_user(user):
res = user.show_info()
print(res)
# 想要实现里氏替换原则, 那么show_info的参数和返回值要相同
3.依赖倒置原则¶
高层模块不应该依赖底层模块, 二者应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。换而言之,要针对接口编程,而不是针对实现编程。总而言之,要遵循“国家规范”(前面讲过的哦)进行编程。
4.接口隔离原则¶
使用多个专门的接口,而不是使用单一的总接口,即高层代码不应该依赖那些它不需要的接口。
举个例子:
假设我们写一个Animal抽象类,这个类定义了walk、swim、fly方法。然后我们有Tiger、Frog、duck这三个类要去实现这个Animal抽象类。我们知道老虎会走,但是它不会游泳(我也不太清楚)和飞。青蛙会走(跳就算走吧)会游泳,但是它不会飞。鸭子就会走、游泳、飞了。这里面,那些动物不会的方法就是不需要的。所以很明显,我们这里的Animal抽象类就不合适了,所以我们要进行接口隔离,即把这个Animal抽象类分为几个抽象类: LandAnimal、WaterAnimal、SkyAnimal。老虎继承LandAnimal,鸭子继承LandAnimal和WaterAnimal,鸭子继承所有抽象类。
下面看看具体代码实现:
1.错误的方法¶
from abc import ABCMeta, abstractmethod
class Animal(mateclass=ABCMeta):
@abstractmethod
def walk(self):
pass
@abstractmethod
def swim(self):
pass
@abstractmethod
def fly(self):
pass
class Tiger(Animal):
def walk(self):
print('老虎走路')
# 我们应该知道抽象类的所有方法都应该实现,否则你懂的
def swim(self):
print('老虎游泳?') # 应该不合理
def fly(self):
print('老虎飞?????') # 显然不合理
class Forg(Animal):
def walk(self):
print('青蛙走路')
def swim(self):
print('青蛙游泳')
def fly(self):
print('青蛙飞?????') # 显然不合理
class Duck(Animal):
# 鸭子好牛逼啊
def walk(self):
print('鸭子走路')
def swim(self):
print('鸭子游泳')
def fly(self):
print('鸭子飞')
2.正确写法¶
from abc import ABCMeta, abstractmethod
# 拆分为多个抽象类
class LandAnimal(mateclass=ABCMeta):
@abstractmethod
def walk(self):
pass
class WaterAnimal(mateclass=ABCMeta):
@abstractmethod
def swim(self):
pass
class SkyAnimal(mateclass=ABCMeta):
@abstractmethod
def fly(self):
pass
class Tiger(LandAnimal):
def walk(self):
print('老虎走路')
class Forg(LandAnimal, WaterAnimal): # 分别继承抽象类
def walk(self):
print('青蛙走路')
def swim(self):
print('青蛙游泳')
class Duck(LandAnimal, WaterAnimal, SkyAnimal): # 分别继承抽象类
# 鸭子好牛逼啊
def walk(self):
print('鸭子走路')
def swim(self):
print('鸭子游泳')
def fly(self):
print('鸭子飞')
5.单一职责原则¶
不要存在多余一个导致类变更的原因。即一个类只负责一项职责。