我在前面的堆棧溢出回答中寫了我對靜態(tài)類的想法:單方法類-最佳方法?
我以前喜歡用靜態(tài)方法填充的實用程序類。他們對助手方法進行了很好的整合,否則會導(dǎo)致冗余和維護混亂。他們非常容易使用,沒有實例化,沒有處理,只是火‘不’忘記。我想這是我第一次無意中嘗試創(chuàng)建一個面向服務(wù)的體系結(jié)構(gòu)-許多無狀態(tài)服務(wù)只是完成了他們的工作,而沒有其他任何東西。然而,隨著一個系統(tǒng)的發(fā)展,龍就要來了。
多態(tài)
假設(shè)我們有UtilityClass的方法。突然,我們需要稍微改變一下功能。大多數(shù)功能是相同的,但我們?nèi)匀恍枰膸讉€部分。如果不是靜態(tài)方法,我們可以創(chuàng)建一個派生類并根據(jù)需要更改方法內(nèi)容。當然,如果我們只需要在舊方法之前或之后添加功能,我們就可以創(chuàng)建一個新類,并在其中調(diào)用舊類-但這太糟糕了。
界面問題
由于邏輯原因,不能通過接口定義靜態(tài)方法。由于我們不能覆蓋靜態(tài)方法,所以當我們需要通過它們的接口傳遞它們時,靜態(tài)類是無用的。這使我們無法使用靜態(tài)類作為策略模式的一部分。我們可以通過傳遞委托而不是接口.
測試
這基本上與上面提到的界面問題密切相關(guān)。由于我們交換實現(xiàn)的能力非常有限,我們在用測試代碼替換生產(chǎn)代碼時也會遇到困難。同樣,我們可以將它們封裝起來,但這將要求我們修改代碼的大部分,以便能夠接受包裝器而不是實際的對象。
胎圈
由于靜態(tài)方法通常被用作實用方法,實用方法通常有不同的用途,所以我們很快就會得到一個包含非一致性功能的大類-理想情況下,每個類在系統(tǒng)中應(yīng)該有一個單一的用途。我寧愿有五倍的課程,只要他們的目的是明確的。
參數(shù)蠕變
首先,這個可愛而又天真的靜態(tài)方法可能只需要一個參數(shù)。隨著功能的增加,添加了幾個新的參數(shù)。不久,會添加更多的參數(shù),這些參數(shù)是可選的,因此我們創(chuàng)建了方法的重載(或者只是在支持它們的語言中添加默認值)。不久,我們就有了一個采用10個參數(shù)的方法。只有前三個是真正需要的,參數(shù)4-7是可選的。但如果指定了參數(shù)6,也需要填寫7-9.如果我們創(chuàng)建一個類的唯一目的是做這個靜態(tài)方法所做的事情,我們就可以通過在構(gòu)造函數(shù)中接受所需的參數(shù)來解決這個問題,并允許用戶通過屬性設(shè)置可選值,或者同時設(shè)置多個相互依賴的值的方法。而且,如果一個方法已經(jīng)發(fā)展到如此復(fù)雜的程度,那么它很可能需要在它自己的類中。
要求使用者無緣無故地創(chuàng)建類的實例。
最常見的論點之一是:為什么要求我們類的使用者創(chuàng)建一個實例來調(diào)用這個單一的方法,而之后卻不使用這個實例?在大多數(shù)語言中,創(chuàng)建類的實例是非常廉價的操作,因此速度不是問題。向使用者添加額外的代碼行對于將來為更易于維護的解決方案奠定基礎(chǔ)來說是一項低成本的工作。最后,如果您想避免創(chuàng)建實例,只需為您的類創(chuàng)建一個允許容易重用的單例包裝器-盡管這確實使您的類成為無狀態(tài)的要求。如果它不是無狀態(tài)的,則仍然可以創(chuàng)建處理一切的靜態(tài)包裝器方法,同時也可以為您提供長期的所有好處。最后,您還可以創(chuàng)建一個類來隱藏實例化,就好像它是一個單例:MyWrapper.Instance是一個只返回的屬性new MyClass();
只有西斯的交易才是絕對的。
當然,我不喜歡靜態(tài)方法也有例外。對于靜態(tài)方法來說,不存在任何膨脹風(fēng)險的真正實用程序類是很好的例子-System.Convert作為一個例子。如果您的項目是一次性的,不需要將來的維護,那么總體架構(gòu)確實不是非常重要的-靜態(tài)的或非靜態(tài)的,并不是真正重要的-但是,開發(fā)速度確實很重要。
標準,標準!
使用實例方法并不妨礙您也使用靜態(tài)方法,反之亦然。只要有理由背后的差別和它是標準化的。沒有什么比查看具有不同實現(xiàn)方法的業(yè)務(wù)層更糟糕的了。