面向对象设计的七大设计原则
2024-09-20
什么是面向对象编程?
设计模式是针对面向对象编程这种编程范式的. 那么在学习设计模式之前我们也要理解什么是 面向对象编程. 面向对象编程是在问题中提取出不同的对象, 而每个对象都有自己的属性和行为. 我们解决问题的过程就是对象与对象之间通过"行为"交互来完成的.
面向对象与面向过程的区别?
与面向对象编程(OOP)相对应的, 还有面向过程编程(POP). 这两种编程范式分别代表了两种代码组织的思想. 我们将以写一个下五子棋的小程序为例, 来看一下两种不同的思想会如何来组织下棋这个相同的功能.
面向过程(POP)
对于下棋这件事情, 我们分为显示棋盘, 下棋和检查胜利几个步骤. 通过不断循环几个函数来达成下棋的功能.
可以参考下面的伪代码:
play_chess.py
# 初始化棋盘
def initCheckerboard()
# 显示棋盘
def showCheckerboard(board)
# 下棋
def play(board, player, row, column)
# 检查胜利
def victoryConditionCheck(board, player)
# 主函数入口
if __name__ == "__main__":
initCheckerboard()
curPlayer = player1
while not (someoneWin or boardIsFull):
showCheckerboard(board)
row, col = getUserInput(curPlayer)
play(board, curPlayer, row, col)
if victoryConditionCheck(board, curPlayer):
print(">>>当前玩家胜利!")
break
curPlayer = switchPlayer(curPlayer)
面向对象(OOP)
在下棋这个过程中, 我们发现可以提取 棋盘 和 棋手 两个对象. 而显示, 判断是否胜利, 判断棋盘是否已满, 移动棋子等属于棋盘的动作. 下棋是属于棋手的动作. 于是乎可以得到下面的伪代码:
play_chess.py
# 棋盘类
class CheckerBoard:
def __init__(self):
self.board = []
def show(self)
def play(self)
def victoryConditionCheck(self)
def isFull(self)
class Player:
def __init__(self, playerName):
self.name = playerName
def input(self)
# 主函数入口
if __name__ == "__main__":
board = CheckerBoard()
player1 = Player("Bob")
player2 = Player("Jack")
curPlayer = player1
while not (board.victoryConditionCheck(curPlayer) or board.isFull()):
board.show()
row, col = curPlayer.input()
board.play(curPlayer, row, col)
if board.victoryConditionCheck(curPlayer):
print(f">>>当前玩家{curPlayer.name}胜利!")
break
curPlayer = switchPlayer(curPlayer)
面向对象的优势
- 更加清晰: 可以在对象中分别管理其状态和行为. 面向过程编程通常会混淆这两者.
- 代码重用: 可以通过继承和多态来实现代码的复用. 比如现在除了人类玩家, 另外增加AI玩家, 我们可以直接进行继承而无需添加太多函数.
- 高扩展性: 如果这个时候增加悔棋的功能, 面向对象编程可以通过增加类或者类中的方法来修改, 而无需修改已有的部分.
总结
本栏目将介绍在面向对象编程的过程中需要遵守的类的 7 种设计原则, 以帮助程序员能够更好地管理自己的代码, 能真正意义上发挥面向对象编程的优势.
七个原则之间并不是相互孤立的, 彼此之间存在一定的关联. 一个可能是另一个的加强或者是基础, 违反其中一个可能意味着同时违反其他几种原则. 其中 开闭原则 是面向对象编程的基石, 其他原则可以看作是实现开闭原则的手段和工具.
设计目标
设计方法