從一個注冊模式用例聊開閉價(jià)值
????不知道你們平時(shí)是否使用注冊模式設(shè)計(jì)模式,我一開始的感覺也是它把一簡單的問題變得復(fù)雜,所以我不是非常喜歡,但我又非常追求代碼的開閉,所以我又常常不得不用它。
????我的需求是這樣的,我有以下兩個類,一個叫Str,一個叫Int,它并非是python的built-in類型,而是在其基礎(chǔ)上做一定的處理。我處理的最終目的是能夠讓它變成SQL語句。
????假設(shè)他們是這樣的:
????現(xiàn)在我有一個Raw的類型,我接受一個原生的python對象,它可能是str,可能是int,它還可能是float/bool/tuple/list/set甚至NoneType(更多的情況我沒有在例子中展示),我需要根據(jù)Raw區(qū)別這個對象的type并創(chuàng)建屬于我自己的IType。一開始我覺得這個問題很簡單,因?yàn)橹貙慱_new__加上if語句就可以,比如這樣:
????這個異??梢栽赺_new__中直接拋出,也可以允許它創(chuàng)建一個Raw對象,在調(diào)用它的to_string方法時(shí)拋出。我暫時(shí)沒有覺得這兩種行為有什么優(yōu)劣(如果你們覺得有很大區(qū)別可以提出來)。我覺得這個問題圓滿解決了。
????問題是在于,當(dāng)我需要處理的type變多的時(shí)候,我都工作就變得很復(fù)雜,我需要頻繁修改這個if語句。大家都知道,修改if語句等于在開閉上畫一個大大的叉,這是我不能容忍的。
????所以我簡單優(yōu)化了一下,在左思右想后,我覺得我適當(dāng)應(yīng)用了注冊模式:
????當(dāng)然這個代碼是一個例子,它直接在__new__中拋出了異常,但這不重要。
????這段代碼也是可以優(yōu)化的,比如給Raw創(chuàng)建一個create方法(這樣做的意義有些模糊,具體是重寫__new__讓其返回不同的類型,還是規(guī)定統(tǒng)一調(diào)用create方法創(chuàng)建類型,這個問題其實(shí)我也沒想出比較滿意的答案,本質(zhì)在于你是否需要一個create去取代__init__或者_(dá)_new__這個過程,或許在其它語言里面是很有必要的,因?yàn)樗鼈儾灰欢ㄓ衉_new__這種魔術(shù)方法);在每個類(Str,Numeric)中創(chuàng)建create方法,甚至給它寫一個Factory(這里涉及到了工廠模式,但是這個例子其實(shí)很簡單,我并不認(rèn)為這里給每一個類型增加一個工廠有什么意義),然后在工廠里面寫這個create,并對所有的工廠做出要求實(shí)現(xiàn)這個create。簡單的問題復(fù)雜化也是我不太喜歡的,所以我就一切從簡了。
????但我發(fā)現(xiàn)了一個很嚴(yán)肅的問題,我現(xiàn)在從修改if語句變成了修改一個dict,我的工作量減少了。但是:
????修改一個if語句,和修改一個dict,有什么本質(zhì)的區(qū)別呢?不還是對修改開放的嗎?
????所以我只能再折騰一下,搞一個注冊類:
????這樣是真的實(shí)現(xiàn)了,當(dāng)我需要重新處理一個類的時(shí)候,我只需要新增一行register。
????它確實(shí)實(shí)現(xiàn)了開閉。
????但它讓代碼變簡單了嗎?沒有。所以一切的價(jià)值都在于開閉上。問題是開閉真的有價(jià)值嗎(這個問題似乎答案肯定是:是的。但我換種問法,我們都知道開閉是為了增加代碼可讀性,降低維護(hù)成本,在我當(dāng)前需求下,我去修改if語句,維護(hù)成本真的很高嗎?我編寫注冊類的時(shí)間成本是否和我后續(xù)的維護(hù)成本匹配?我不知道,因?yàn)榇蠹視f,我自己也會說:你自己到最后也無法知曉你的需求會變得多么的復(fù)雜)
????所以這是個很玄學(xué)的問題,仁者見仁智者見智,歡迎大家指摘。