作者:haroel
鏈接:https://www.zhihu.com/question/56527586/answer/149837964
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
理論有時學起來很枯燥,所以說2個例子。
1. 繼承。
拿cocos2d-x遊戲引擎的FileUtils來做個說明,遊戲業務功能層面我們只用調用 FileUtils類的靜態 getInstance方法,FileUtils::getInstance()->func() 。。。 就可以調用需要的資源。
FileUtils類實現了許多通用的處理方法,它是一個單例,FileUtils.h裏面聲明瞭 static FileUtils* getInstance();但FileUtils.cpp裏沒有getInstance實現代碼(FileUtils可以看成抽象類)。
getInstance的實現是放在不同平臺的FileUtils子類,比如FileUtils-Apple,FileUtils-Android和FileUtils-win32(當然你也可以繼續繼承FileUtils-Apple等等來實現更多功能),這幾個類都繼承了FileUtils,並實現了static FileUtils* getInstance()。 用這種方式,增加一個新平臺可以完全不用修改已有的代碼,代碼結構組織也非常清晰。 當然,如果全部靜態+宏也能實現,不過代碼維護性可能慘不忍睹。
github: cocos2d/cocos2d-x
2. 多核實現。
單例模式的目的是爲了創建一個唯一的全局對象。
抽象點的比喻,某地有一個工廠A1,B公司是工廠的管理機構,在實現上,A1的系統裏有一個單例類A1來統籌管理其生產業務流程。現在要擴大生產規模,在另外一個地方新建一家工廠A2,兩家業務相似但不完全相同,現在B要同時管理A1和A2。
這裏A1和A2構成了2個模塊,每個模塊內部獨立,互不干涉,大概代碼是這樣,應該看得懂
<img src="https://pic1.zhimg.com/50/v2-79b85e7e58093172197a84e12efcd655_hd.jpg" data-rawwidth="892" data-rawheight="1014" class="origin_image zh-lightbox-thumb" width="892" data-original="https://pic1.zhimg.com/v2-79b85e7e58093172197a84e12efcd655_r.jpg">
A2和A1類似,這裏不詳細寫了,A的getInstance需要傳一個參數。 用這種方式,A1和A2依然是全局唯一,B公司系統在調用時依然只需要使用A::getInstance("Ai"),就可以控制任何一個子工廠的生產。同樣的,如果未來再建立新模塊或者刪除已有模塊代碼,B公司系統可不做修改就能滿足需求。
(如果還不理解,建議去了解下pureMVC的多核原理)
我總結出來大概就這兩種。相比而言,用類比用靜態來實現單例更加合理,結構和擴展性也相比較好。當然,如果你的系統非常小,就是一快餐式的代碼,根本不用去考慮擴展和維護,單例隨你怎麼用了,根本沒有什麼非要用實例化來實現單例的說法。