場景

針對園區停車資訊,需要對各個公司提供的停車資料進行整合並錄入自家公司的大資料平臺

資料的錄入無外乎就是對資料的增刪改查

下面上一個常規的寫法(未符合依賴倒置),整合來自 長安和豐田 的停車資料

class Changan(object):
def __init__(self):
self.type = 'changan' def ca_add(self):
print('%s 新增' % self.type) def ca_del(self):
print('%s 刪除' % self.type) def ca_modify(self):
print('%s 修改' % self.type) def ca_get(self):
print('%s 查詢' % self.type) class Toyota(object):
def __init__(self):
self.type = 'fengtian' def tyt_add(self):
print('%s 新增' % self.type) def tyt_del(self):
print('%s 刪除' % self.type) def tyt_modify(self):
print('%s 修改' % self.type) def tyt_get(self):
print('%s 查詢' % self.type) class Data(object): def __init__(self, car):
self.car = car def data_add(self):
if self.car.type == 'changan':
self.car.ca_add()
else:
self.car.tyt_add() def data_del(self):
if self.car.type == 'changan':
self.car.ca_del()
else:
self.car.tyt_del() def data_mofify(self):
if self.car.type == 'changan':
self.car.ca_modify()
else:
self.car.tyt_modify() def data_get(self):
if self.car.type == 'changan':
self.car.ca_get()
else:
self.car.tyt_get() if __name__ == '__main__':
ca = Changan()
tyt = Toyota()
autosystem = Data(ca)
autosystem.data_add()
autosystem.data_del()
autosystem.data_modify()
autosystem.data_get()
autosystem.car = tyt
print('*' * 50)
autosystem.data_add()
autosystem.data_del()
autosystem.data_modify()
autosystem.data_get()

執行的結果如下

changan 新增
changan 刪除
changan 修改
changan 查詢
**************************************************
fengtian 新增
fengtian 刪除
fengtian 修改
fengtian 查詢

可以看到最後的Data類是一個簡單工廠,通過面向流程的方式對資料進行增刪改查,上層的Data類永遠都要依賴下層的Changan類和Toyota類,假設未來Changan類和Toyota類因為需求變更導致實現方式變了,那麼Data類也會跟著改,或者未來又來一家新的廠商鈴木Suzuki,那麼在Data又要多寫很多if else。這樣的改動對於程式設計師來說是致命的,每一次變動需要改動的地方都很多,問題油然而生。

如何解決

遵循依賴倒置原則,根據

"程式要依賴於抽象介面,不要依賴於具體實現。"

通過changan、toyota這些類的公共性,把處理資料的方法通過介面抽象出來

import abc

class DataProcessing(metaclass=abc.ABCMeta):
"""
抽象類
抽象新增改查
"""
@abc.abstractmethod
def data_add(self, *args, **kwargs):
pass @abc.abstractmethod
def data_del(self, *args, **kwargs):
pass @abc.abstractmethod
def data_modify(self, *args, **kwargs):
pass @abc.abstractmethod
def data_get(self, *args, **kwargs):
pass class Changan(DataProcessing):
def __init__(self):
self.type = 'changan' def data_add(self):
print('%s 新增' % self.type) def data_del(self):
print('%s 刪除' % self.type) def data_modify(self):
print('%s 修改' % self.type) def data_get(self):
print('%s 查詢' % self.type) class Toyota(DataProcessing):
def __init__(self):
self.type = 'fengtian' def data_add(self):
print('%s 新增' % self.type) def data_del(self):
print('%s 刪除' % self.type) def data_modify(self):
print('%s 修改' % self.type) def data_get(self):
print('%s 查詢' % self.type) class Data(object): def __init__(self, car):
self.car = car def data_add(self):
self.car.data_add() def data_del(self):
self.car.data_del() def data_modify(self):
self.car.data_modify() def data_get(self):
self.car.data_get() if __name__ == '__main__':
ca = Changan()
tyt = Toyota()
autosystem = Data(ca)
autosystem.data_add()
autosystem.data_del()
autosystem.data_modify()
autosystem.data_get()
autosystem.car = tyt
print('*' * 50)
autosystem.data_add()
autosystem.data_del()
autosystem.data_modify()
autosystem.data_get()

執行後結果依然為

changan 新增
changan 刪除
changan 修改
changan 查詢
**************************************************
fengtian 新增
fengtian 刪除
fengtian 修改
fengtian 查詢

以上可看出,增刪改查已經抽象成DataProcessing裡面的方法,以後不管Changan類和Toyota類怎麼變動,或者需要新增一個Suzuki類什麼的,上層的Data類都不用改變,if name == 'main' 後客戶端的呼叫也不需要怎麼改動,程式碼層次也更清晰,便於後續的擴充套件。

文章來自 Yongchin'blog yongchin.xyz