中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中API設計的示例分析

發布時間:2021-09-09 11:32:34 來源:億速云 閱讀:92 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關Java中API設計的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

前言

了解在設計 Java API 時應該運用的一些 API 設計實踐。這些實踐通常很有用,而且可確保 API 能在諸如 OSGi 和 Java Platform Module System (JPMS) 之類的模塊化環境中得到正確使用。有些實踐是規定性的,有些則是禁止性的。當然,其他良好的 API 設計實踐也同樣適用。

OSGi 環境提供了一個模塊化運行時,使用 Java 類加載器概念來強制實施類型可見性封裝。每個模塊都將有自己的類加載器,該加載器將連接到其他模塊的類加載器,以共享導出的包并使用導入的包。

Java 9 引入了 JPMS,后者提供了一個模塊化平臺,使用來自 Java 語言規范的訪問控制概念來強制實施類型可訪問性封裝。每個模塊都定義了哪些包將被導出,從而可供其他模塊訪問。默認情況下,JMPS 層中的模塊都位于同一個類加載器中。

一個包可以包含一個 API。這些 API 包的客戶端有兩種角色:API 使用者和 API 提供者。API 使用者使用 API 提供者實現的 API。

在以下設計實踐中,我們將討論包的公共部分。包的成員和類型不是公共的,或者說是受保護的(即私有或默認可訪問的),無法從包的外部訪問它們,所以它們是包的實現細節。

Java 包必須是一個有凝聚力、穩定的單元

Java 包的設計必須確保它是一個有凝聚力且穩定的單元。在模塊化 Java 中,包是模塊之間共享的實體。一個模塊可以導出一個包,以便其他模塊可以使用這個包。因為包是在模塊之間共享的單元,所以它必須有凝聚力,因為包中的所有類型必須與包的特定用途相關。

不鼓勵使用混雜的包,比如 java.util,因為這種包中的類型通常是彼此不相關的。這類沒有凝聚力的包可能導致大量依賴項,因為包的不相關部分會引用其他不相關的包,而且對包的某個方面的更改會影響依賴于此包的所有模塊,即使模塊可能并未實際使用該包的被修改部分。

由于包是一個共享單元,所以它的內容必須是眾所周知的,而且隨著包在未來版本中的演變,只能以兼容方式更改所包含的 API。這意味著包不能支持 API 超集或子集;例如,可以將 javax.transaction 視為內容不穩定的包。

包的用戶必須能夠了解包中提供了哪些類型。這也意味著包應由單個實體(例如一個 jar 文件)提供,不得跨多個實體進行拆分,因為該包的用戶必須知道整個包的存在。

此外,該包必須以兼容方式實現在未來版本中的演變。因此,應該對包進行版本控制,而且其版本號必須根據語義版本控制規則進行演變。

但最近我意識到,針對包的主版本更改的語義版本控制建議是錯誤的。包的演變必須是功能的增加。在語義版本控制中,這會增加次要版本。

當刪除功能時,您會對包執行不兼容的更改,而不是增加主版本, 您必須改用一個新的包名,而讓原始包保持可兼容。在對包執行不兼容的更改時,應該改用新的包名,而不是更改主版本。

最小化包耦合

一個包中的類型可以引用其他包中的類型,例如,某個方法的參數類型和返回類型,以及某個字段的類型。這種包間耦合會在包上造成所謂的使用限制。這意味著 API 使用者必須使用 API 提供者引用的相同包,以便他們都能了解所引用的類型。

一般而言,我們希望最小化這種包耦合,以便最小化包上的使用限制。這可以簡化 OSGi 環境中的連接解析,并最大限度地減少依賴扇出,從而簡化部署。

接口優先于類

對于 API,接口優先于類。這是一種相當常見的 API 設計實踐,對模塊化 Java 也很重要。接口的使用提高了實現的自由度,還支持多種實現。

接口對于讓 API 使用者與 API 提供者分離至關重要。無論是實現接口的 API 提供者,還是調用接口上的方法的 API 使用者,都允許使用包含 API 接口的包。

通過這種方式,API 使用者不會直接依賴于 API 提供者。它們都只依賴于 API 包。

除接口外,抽象類有時也是一種有效的設計選擇,但接口通常是首選,尤其是考慮到接口的最新改進允許添加 default 方法。

最后,API 通常需要許多小的具體類,比如事件類型和異常類型。這沒什么問題,但這些類型通常應該是不可變的且不被 API 使用者用來創建子類。

避免靜態

應在 API 中要避免靜態。類型不應包含靜態成員。靜態工廠也應該避免。實例的創建應與 API 分離。例如,API 使用者應通過依賴注入或者 OSGi 服務注冊表或 jPMS 中的 java.util.ServiceLoader 之類的對象注冊表來接收 API 類型的對象實例。

避免靜態也是一種創建可測試的 API 的良好實踐,因為靜態不容易模仿。

單例

API 設計中有時存在單例對象。但是,不應通過靜態 getInstance 方法或靜態字段等靜態對象來訪問單例對象。當需要使用單例對象時,該對象應由 API 定義為單例,并通過上文提到的依賴注入或對象注冊表提供給 API 使用者。

避免類加載器假設

API 通常具有可擴展性機制,API 使用者可在其中提供 API 提供者必須加載的類名。然后,API 提供者必須使用 Class.forName(可能使用線程上下文類加載器)來加載該類。這種機制會假定從 API 提供者(或線程上下文類加載器)到 API 使用者的類可見性。

API 設計必須避免類加載器假設。模塊化的一個主要特點是類型封裝。一個模塊(例如 API 提供者)不能對另一個模塊(例如 API 使用者)的實現細節具有可見性/可訪問性。

API 設計必須避免在 API 使用者與 API 提供者之間傳遞類名,而且必須避免與類加載器分層結構和類型可視性/可訪問性有關的假設。

為了提供可擴展性模型,API 設計應讓 API 使用者將類對象,或者最好將實例對象,傳遞給 API 提供者。這可以通過 API 中的一個方法或 OSGi 服務注冊表之類的對象注冊表來完成。請參見白板模式。

在 JPMS 模塊中不使用 java.util.ServiceLoader 類時,也會受到類加載器假設的影響,因為它假設所有提供者都對線程上下文類加載器或所提供的類加載器可見。

此假設在模塊化環境中通常是不成立的,但 JPMS 允許通過模塊聲明來聲明模塊提供或使用了一個 ServiceLoader 托管服務。

不進行持久性假設

許多 API 設計都假設只有一個構造階段,對象在該階段被實例化并添加到 API,但是忽略了動態系統中可能發生的解構階段。

API 設計應考慮到,對象可以添加,也可以刪除。例如,大多數監聽器 API 都允許添加和刪除監聽器。但是,許多 API 設計僅假設對象可以添加,并且從未刪除這些對象。例如,許多依賴注入系統無法撤銷注入的對象。

在 OSGi 環境中,可以添加和刪除模塊,因此能夠兼顧到此類動態的 API 設計非常重要。OSGi Declarative Services 規范為OSGi 定義了一個依賴注入模型,該模型支持這些動態操作,包括撤銷注入對象。

明確規定 API 使用者和 API 提供者的類型角色

如前言中所述,API 包的客戶端有兩種角色:API 使用者和 API 提供者。API 使用者使用 API,而 API 提供者實現 API。對于 API 中的接口(和抽象類)類型,API 設計一定要明確規定哪些類型僅由 API 提供者實現,哪些類型可由 API 使用者實現。例如,監聽器接口通常由 API 使用者實現,而實例被傳遞給 API 提供者。

API 提供者對 API 使用者和 API 提供者實現的類型更改都很敏感。提供者必須實現 API 提供者類型中的任何新更改,而且必須了解且可能調用 API 使用者類型中的任何新更改。

API 使用者通常可以忽略 API 提供者類型的(兼容)更改,除非它希望通過更改來調用新功能。但是 API 使用者對 API 使用者類型的更改很敏感,而且可能需要修改才能實現新功能。

例如,在 javax.servlet 包中,ServletContext 類型由 API 提供者(比如 servlet 容器)實現。向 ServletContext 添加新方法需要更新所有 API 提供者來實現新方法,但 API 使用者無需執行更改,除非他們希望調用該新方法。

但是,Servlet 類型由 API 使用者實現,向 Servlet 添加新方法需要修改所有 API 使用者來實現新方法,還需要修改所有 API 提供者來使用該新方法。因此,ServletContext 類型有一個 API 提供者角色,Servlet 類型有一個 API 使用者角色。

由于通常有許多 API 使用者和很少的 API 提供者,所以在考慮更改 API 使用者類型時,必須非常謹慎地執行 API 演變,而 API 提供者類型更改的要求更加寬松。

這是因為,您只需要更改少數 API 提供者來支持更新的 API,但您不希望在更新 API 時需要更改許多現有的 API 使用者。僅當 API 使用者希望使用新 API 時,API 使用者才需要執行更改。

OSGi Alliance 定義了文檔注釋、ProviderType 和 ConsumerType 來標記 API 包中的類型角色。這些注釋包含在 osgi.annotation jar 中供您的 API 使用。

感謝各位的閱讀!關于“Java中API設計的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

万宁市| 闵行区| 南江县| 泸西县| 海门市| 襄汾县| 湘潭县| 朝阳县| 西乌珠穆沁旗| 萝北县| 南阳市| 平阳县| 波密县| 克什克腾旗| 佛冈县| 宾川县| 乌审旗| 涡阳县| 饶平县| 长乐市| 无棣县| 北海市| 汉源县| 兴业县| 揭西县| 天长市| 南漳县| 寿宁县| 化隆| 资源县| 南丰县| 连云港市| 柯坪县| 华亭县| 会东县| 鄂伦春自治旗| 三明市| 阿勒泰市| 上蔡县| 西贡区| 二连浩特市|