巧用拦截器:高效的扩展点设计
最近在設計框架時,需要設計一類擴展點,發現不能簡單地繼承或使用事件來給使用者提供 API。最終使用攔截器模式解決了 API 的設計。
?
擴展點使用場景
該擴展點的使用場景如下:
?
擴展點設計方案選型
在框架設計時,擴展點設計主要通過幾種類型的 API 來提供:虛方法、事件、接口。(關于擴展點的設計,詳細的內容,參見:《Framework Design Guidelines 2nd Edition》第六章,擴展性設計。)而最常用、最方便使用者使用的擴展點則是前兩個:虛方法和事件。
前兩種擴展點設計方案的主要區別在于:
可以看出,如果是想設計一類提供給繼承體系外類型進行擴展的擴展點, 虛方法、事件兩類 API 都不合適。那我們只能在第三種方式上想辦法:接口。接口的設計則非常靈活,而其實我上面描述的場景會經常遇到,所以應該提取出一類設計模式。經過一番思考,我發現其實攔截器模式比較適合該場景。攔截器模式本身注重對消息、方法的攔截處理,是一種繼承體系外的擴展方法,并被大量用于 AOP 的實現。在這里采用該模式,我們更加關注其在真正核心方法調用前后的擴展機制、以及核心方法的阻斷機制,以及最終擴展 API 提供的形式。
?
實現
該模式放到 Rafy 中實現提交時的擴展點后,類圖如下:
?
擴展點使用方法也較簡單,使用者繼承攔截器,編寫相應的擴展邏輯即可:
有一個細節需要注意:上圖中能看到,方法的第一個參數也是一個自定義的參數類型 SubmitArgs。但是由于攔截器是一種鏈式調用,所以這個類型可以采用值類型;在此方法被大量調用時,相對于事件的擴展機制,沒有大量的冗余對象。
在啟動時,加入以下代碼就可以把該攔截器添加到保存的攔截器列表中:
?
總結
攔截器模式實現起來比較簡單,該模式的結構非常類似于 GOF 中的職責鏈模式,只是關注點不同。在使用它作為擴展點時,對于使用者來說也比較易用,而且性能相對于事件機制來說更好,所以可以直接作為一種常用的擴展點設計方案。
總結
以上是生活随笔為你收集整理的巧用拦截器:高效的扩展点设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 授权后接口调用(UnionID)
- 下一篇: Objective-C 工厂方法