Qt源碼中的設(shè)計(jì)模式:面向?qū)ο笤O(shè)計(jì)原則與GoF的23個(gè)設(shè)計(jì)模式

Qt源碼的設(shè)計(jì)優(yōu)秀程度,相信使用過Qt的程序員都會(huì)有所感受。若深入源碼去體會(huì),則感受更深。廢話不多說,先說目的。筆者希望通過解析Qt框架中使用到的設(shè)計(jì)模式和面向?qū)ο笤O(shè)計(jì)原則,讓讀者包括自己獲得兩方面的好處:

  1. C++程序架構(gòu)設(shè)計(jì)能力的提升。解析Qt框架中的設(shè)計(jì)模式,能夠讓讀者體會(huì)到大佬們是如何使用設(shè)計(jì)模式的,從而領(lǐng)悟設(shè)計(jì)模式到底怎么用,至少清楚設(shè)計(jì)模式絕非雞肋。

  2. 精通Qt框架的使用,并且有能力修改Qt源代碼。Qt源代碼并非毫無漏洞,如果深度使用Qt進(jìn)行應(yīng)用軟件開發(fā),遲早會(huì)遇到Qt中的坑(筆者遇到過早期版本中QSettings類解析ini文件的崩潰問題)。有一些bug在Qt后續(xù)版本中已經(jīng)進(jìn)行修復(fù),可以通過更新Qt版本進(jìn)行修復(fù)。但如果沒有修復(fù),且開發(fā)項(xiàng)目中繞不開這個(gè)問題,那就是考驗(yàn)程序員水平的時(shí)候了。

那么,Qt中如何體現(xiàn)出面向?qū)ο笤O(shè)計(jì)原則與設(shè)計(jì)模式?這里先簡單總結(jié)一下。關(guān)于面向?qū)ο笤O(shè)計(jì)原則:

  1. 開閉原則(Open-Closed Principle,OCP):Qt框架對擴(kuò)展開放,對修改封閉。例如,QWidget類的paintEvent()方法可以被子類重載,以實(shí)現(xiàn)不同的繪制行為,而無需修改QWidget類的源代碼。

  2. 里氏替換原則(Liskov Substitution Principle,LSP):Qt框架中的很多類都可以通過繼承和多態(tài)來實(shí)現(xiàn)功能的替換和擴(kuò)展。例如,QPaintDevice是一個(gè)抽象基類,其子類包括QPixmap、QImage、QWidget等,這些子類都可以用來進(jìn)行繪圖,而用戶無需關(guān)心它們的具體類型。

  3. 依賴倒置原則(Dependency Inversion Principle,DIP):Qt框架中的很多類都依賴于抽象而不是具體實(shí)現(xiàn)。例如,QPainter類可以在任何實(shí)現(xiàn)了QPaintDevice接口的類上進(jìn)行繪圖,而不是直接依賴于特定的類,如QPixmap或QWidget。

  4. 接口隔離原則(Interface Segregation Principle,ISP):Qt框架將大的接口分解為小的、特定的接口,使得類可以只依賴于需要的接口。例如,QIODevice類有很多子類,如QFile、QBuffer、QTcpSocket等,它們都只實(shí)現(xiàn)了與自身功能相關(guān)的一部分接口。

  5. 單一職責(zé)原則(Single Responsibility Principle,SRP):Qt框架中的每個(gè)類都有其單一的職責(zé)。例如,QFile類只負(fù)責(zé)文件的IO操作,而QTextStream類則負(fù)責(zé)提供文本流的接口,它們的職責(zé)清晰、明確。

  6. 合成復(fù)用原則(Composition over Inheritance,COI):合成復(fù)用原則強(qiáng)調(diào)盡量使用組合/聚合關(guān)系達(dá)到復(fù)用的目的,而不是使用繼承。因?yàn)槔^承會(huì)導(dǎo)致過度耦合,并可能導(dǎo)致設(shè)計(jì)變得不靈活。QGraphicsProxyWidget作為代理模式中的代理主題時(shí),與QWidget的關(guān)系是組合,是一種對代理模式的靈活調(diào)整,體現(xiàn)出合成復(fù)用原則。

這些原則在Qt框架的設(shè)計(jì)和實(shí)現(xiàn)中起到了關(guān)鍵的作用,使得Qt框架具有良好的可維護(hù)性和擴(kuò)展性。

關(guān)于具體的設(shè)計(jì)模式方面,Qt使用了GoF中一部分的設(shè)計(jì)模式。從23種設(shè)計(jì)模式的三大類(創(chuàng)建型模式,結(jié)構(gòu)型模式和行為型模式)角度解析,包括:

  1. 創(chuàng)建型模式:
  • 工廠方法(Factory Method):筆者目前沒有在Qt中找到明顯的工廠方法模式的應(yīng)用。

  • 抽象工廠(Abstract Factory):筆者目前沒有在Qt中找到明顯的抽象工廠模式的應(yīng)用。

  • 建造者(Builder):筆者目前沒有在Qt中找到明顯的建造者模式的應(yīng)用。

  • 原型(Prototype):筆者目前沒有在Qt中找到明顯的原型模式的應(yīng)用。(其實(shí)這玩意和C++中通過復(fù)制構(gòu)造函數(shù)實(shí)現(xiàn)深拷貝是差不多的)。

  • 單例(Singleton):在Qt中,有些類只允許有一個(gè)實(shí)例,例如 QApplication。

  1. 結(jié)構(gòu)型模式:
  1. 行為型模式:
  • 責(zé)任鏈(Chain of Responsibility):Qt的事件傳遞機(jī)制使用了責(zé)任鏈模式。參考:Qt源碼中的設(shè)計(jì)模式:事件傳播機(jī)制與責(zé)任鏈模式

  • 命令(Command):Qt的撤銷/重做框架(QUndoStack、QUndoCommand等類)使用了命令模式。參考:Qt源碼中的設(shè)計(jì)模式:撤銷/重做框架與命令模式

  • 解釋器(Interpreter):QRegExp是Qt中解釋器模式的一個(gè)示例,它解析并匹配正則表達(dá)式。

  • 迭代器(Iterator):Qt的容器類(如QList,QVector)提供了迭代器。

  • 中介者(Mediator):筆者目前沒有在Qt中找到明顯的中介者模式的應(yīng)用。

  • 備忘錄(Memento):Qt的QSessionManager提供了一種方式來保存和恢復(fù)應(yīng)用程序的會(huì)話狀態(tài)。

  • 觀察者(Observer):在Qt中,信號和槽的機(jī)制是一種特殊的觀察者模式。參考:Qt信號槽機(jī)制的底層實(shí)現(xiàn)是怎樣的?與ChatGPT老師促膝而談

  • 狀態(tài)(State):Qt的狀態(tài)機(jī)框架(QStateMachine,QState等類)使用了狀態(tài)模式。

  • 策略(Strategy):Qt的布局管理使用了策略模式。

  • 模板方法(Template Method):Qt的事件處理機(jī)制使用了模板方法模式。

  • 訪問者(Visitor):筆者目前沒有在Qt中找到明顯的訪問者模式的應(yīng)用。

關(guān)于這些設(shè)計(jì)模式的具體解析,以及如何在Qt框架中體現(xiàn),會(huì)在后續(xù)的文章中逐一分析。讀者也可以根據(jù)這里提到的大綱,自行挖掘Qt源碼中如何使用了這些設(shè)計(jì)模式,相信會(huì)有不少的收獲。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容