遊戲系統開發繼承帶來的問題

阿元吶發表於2020-11-22

需求例子

原本適用於A模式的觀戰系統,現在需要支援B模式。經過討論之後,主要有以下a、b、c三處不同。

程式碼中如何組織觀戰系統在不同模式的多型行為

繼承

# 建立一個新的子類,繼承原先的observe_player系統
# observe_player.py
class System(timer.TimerObject):
    """組隊模式的觀戰系統與原先的觀戰系統在這三個函式上有區別
    
    """
	def _RequestJoinObserve(self, player_obj, observed_obj=None, is_tips=False, is_dead=False):
		......

	def _SwitchObserve(self, observe_guid, origin_observed_guid, new_target=None, is_change=False):
		......

	def OnRequestSwitchObserve(self, player_obj):
		......

# observe_player_team_mode.py
from game.systems import observe_player
class System(observe_player.System):
    """組隊模式的觀戰系統與原先的觀戰系統在這三個函式上有區別
    
    """
	def _RequestJoinObserve(self, player_obj, observed_obj=None, is_tips=False, is_dead=False):
		......

	def _SwitchObserve(self, observe_guid, origin_observed_guid, new_target=None, is_change=False):
		......

	def OnRequestSwitchObserve(self, player_obj):
		......

動機

  1. 多個子類互不影響,避免想要修改某種模式的觀戰行為時,不小心影響到其他模式。

引起的問題

  1. 觀戰系統交由多名程式開發,其他程式並不知道有子類的存在,常常引起報錯。
  2. 可以抽離出base類,以提醒其他開發者,但這種提醒並不能完全解決上述問題,其他程式在迭代的時候,仍然容易忽視基類的修改對子類的影響,而且哪怕意識到了,也要小心地考慮對多個子類造成的影響。
  3. 這就需要base類的內容儘可能的少,其概念儘可能的通用。

在變化處用變數控制

在a、b、c三處行為處用變數開關控制,符合條件的模式將使用新的行為。

若不同模式的觀戰行為有更多的組合,則需要抽離出觀戰方案配置選項:在a、b、c三處行為處用變數開關控制,並抽象出觀戰方案對其進行填表控制。

選擇這種看上去更簡單的方式,有以下幾個理由:

  1. 不同模式不同行為都放在一處,不容易遺漏。
  2. 本質上來說,僅僅是三處不同,用變數開關簡單地控制已經滿足需求。
  3. 變數開關方便開放給產品配置,而繼承需要使用工廠函式去建立不同子類,僅僅由程式控制。
  4. 繼承從來不是一開始就要做的工作,而是在發現有必要的時候,才開始。

相關文章