📅  最后修改于: 2023-12-03 15:11:42.438000             🧑  作者: Mango
SOLID 原则是面向对象编程(Object Oriented Programming,OOP)中的一个设计原则集合。它们是以下五个原则的缩写:
单一职责原则指的是一个类或者模块应该只负责一项功能。这样可以提高代码的可读性、可维护性和灵活性。类比现实世界中,一个人也应该只有一个主要职责,做好自己的本职工作。
例如,一个厨师只需要做好自己的料理,而不需要去清理餐具或者装修食堂。同样,一个图书管理员也只需要管理图书,而不需要负责计算机网络维护。
在代码中,一个例子是创建一个只负责打印日志的类,而不是让一个类既负责业务逻辑,又负责打印日志。
# 错误示范
class UserData:
def create_user(self, user):
# ...创建用户...
print('User created at', datetime.datetime.now())
# ...\添加用户到数据库...
# 正确示范
class UserData:
def create_user(self, user):
# ...创建用户...
# ...\添加用户到数据库...
class Logger:
def log(self, message):
print(message)
user_data = UserData()
logger = Logger()
user_data.create_user('John Doe')
logger.log('User created at ' + str(datetime.datetime.now()))
开闭原则指的是“开放-封闭”原则。一个类或者模块应该对扩展开放,对修改封闭。换言之,更改类的行为应该是通过添加新功能来实现,而不是修改现有的代码。类似地,一个计算机软件也应该允许添加新的功能,而不是强制修改现有代码。
类比现实世界中,一个建筑也应该留有空间供以后的拓张和装修,而不是被固定在建筑物本身。
在代码中,一个例子是创建一个通用的数据处理类,让它根据传入的参数和类型进行不同的数据处理,而不是在每次需要新的数据处理时都去修改代码。
# 错误示范
class UserData:
def get_users(self):
# ...\从数据库读取所有用户数据...
users = []
for data in fetched_data:
users.append(User(data))
return users
def get_admins(self):
# ...\从数据库读取所有管理员数据...
admins = []
for data in fetched_data:
admins.append(Admin(data))
return admins
# 正确示范
class DataProcessor:
def process(self, data_list, class_type):
processed_data = []
for data in data_list:
processed_data.append(class_type(data))
return processed_data
user_data = UserData()
data_processor = DataProcessor()
all_users = user_data.get_users()
all_admins = user_data.get_admins()
processed_users = data_processor.process(all_users, User)
processed_admins = data_processor.process(all_admins, Admin)
里氏替换原则指的是父类对象应该能够被它的子类对象所替换,而不影响程序的正确性。也就是说,在一个继承关系中,子类不应该改变父类所拥有的特性。
类比现实世界中,一个“鸟”应该可以被“鸽子”或者“老鹰”这样的子类所替换,而不会影响它所拥有的通用特性,例如“能飞”。
在代码中,一个例子是创建一个抽象的基类,让所有的子类都继承并保持一致的接口和功能。
# 错误示范
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Square(Rectangle):
def __init__(self, side):
super().__init__(side, side)
# 正确示范
class Shape:
def area(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
接口隔离原则指的是应该尽可能地将接口拆分成更小的、更具体的接口。这样可以避免在实现接口时被强迫实现一些不需要的方法。也就是说,接口应该仅包含客户端需要使用的方法,而不应该包含其它的不必要的方法。
类比现实世界中,一个“动物学家”不需要了解一只鸟是如何飞行的。她只需要关心鸟是哪一类动物、鸟的外貌和行为。
在代码中,一个例子是创建一个只包含必要方法的接口,而不是让一个类去实现不需要的方法。
# 错误示范
class User:
def register(self, username, password):
# ...注册用户...
def login(self, username, password):
# ...登录...
def logout(self, username):
# ...退出...
class UserWebAPI:
def get_user_data(self, user_id):
# ...获取用户数据...
def get_user_info(self, user_id):
# ...获取用户信息...
# 正确示范
class UserAuth:
def register(self, username, password):
# ...注册用户...
def login(self, username, password):
# ...登录...
def logout(self, username):
# ...退出...
class UserData:
def get_user_data(self, user_id):
# ...获取用户数据...
class UserInfo:
def get_user_info(self, user_id):
# ...获取用户信息...
依赖反转原则指的是高层模块不应该依赖于低层模块,而是应该依赖于抽象接口。同时,抽象接口不应该依赖于具体实现,具体实现应该依赖于抽象接口。这样可以提高代码的灵活性、可扩展性、可维护性和可测试性。
类比现实世界中,一个高层经理不应该依赖于一个底层员工,而是应该依赖于公司的组织结构和规章制度。在公司中,具体实现并不重要,重要的是满足公司既定的规定和流程。
在代码中,一个例子是创建一个抽象接口和一个或多个具体实现,让高层模块依赖于抽象接口,而不是具体实现。
# 错误示范
class EmailSender:
def send_email(self, message, recipients):
# ...发送电子邮件...
class NotificationService:
def __init__(self):
self.email_sender = EmailSender()
def send_notification(self, message, recipients):
self.email_sender.send_email(message, recipients)
# 正确示范
class MessageSender:
def send(self, message, recipients):
pass
class EmailSender(MessageSender):
def send(self, message, recipients):
# ...发送电子邮件...
class NotificationService:
def __init__(self, message_sender):
self.message_sender = message_sender
def send_notification(self, message, recipients):
self.message_sender.send(message, recipients)
email_sender = EmailSender()
notification_service = NotificationService(email_sender)
notification_service.send_notification('New message', ['example@example.com'])
以上就是 SOLID 原则的五个方面及其代码实现的例子。通过遵循这些原则,可以创建出更好的代码库和更健壮的代码。