背景介紹
在一個復雜的 Android 項目中,我們通常會有多個庫(lib),而主應用程序(app)依賴所有這些庫。目前遇到的問題是,在這些庫中,libAd
需要獲取 libVip
的 VIP 等級狀態,但這兩個庫之間沒有直接依賴關系。
問題分析
一種不太優雅的解決方案是直接讓 libAd
依賴 libVip
,這樣雖然能快速解決問題,但會帶來多個潛在缺點:
-
依賴混亂:
當庫之間形成直接依賴時,會導致項目的依賴關系變得復雜且難以管理。每增加一個新的依賴,都可能影響到項目的構建時間、性能以及可移植性。 -
違反單一職責原則(Single Responsibility Principle, SRP):
libAd
本應專注于廣告相關功能,而不是負責管理 VIP 狀態。如果它依賴于libVip
,則意味著它同時承擔了額外的責任,使其更難維護。 -
降低模塊化和可復用性:
增加不必要的依賴會使得庫變得不夠獨立,降低了它們的可重用性。此后若要將這些庫用于其他項目,還需要處理不相關的依賴關系。 -
演變成緊耦合系統:
隨著項目的發展,如果每個模塊都通過直接依賴來獲取所需信息,整個系統將逐漸演變為緊耦合的體系結構。這種結構讓系統中的一個變化可能導致一連串的調整,增加了維護成本和復雜性。 -
違反開閉原則(Open/Closed Principle, OCP):
系統應該對擴展開放,對修改關閉。直接依賴使得系統在面對需求變化時,需要頻繁修改已有代碼,而不是通過擴展實現新功能。
因此,我們需要尋找一種更好的方法來實現跨庫的數據傳遞,以保持庫之間的獨立性和系統的靈活性,同時遵循良好的設計原則,從而提高代碼的可維護性和可擴展性。
簡單方案的缺陷
一個簡單的方法是利用已有的 libNet
庫作為中介。這種方法基于以下前提和依賴關系:
-
現有依賴關系:
在當前項目結構中,libAd
和libVip
都已經依賴于libNet
。這意味著它們都能夠訪問libNet
提供的功能,而無需額外增加任何新的直接庫間依賴。 -
中介模式的應用:
- 通過使用
libNet
作為中介,我們可以在不直接修改libAd
和libVip
的情況下,實現它們之間的數據傳遞。具體做法如下:- 當
libVip
的 VIP 等級發生變化時,它會調用libNet
的setVipInfo(String info)
方法,將最新的信息存儲在libNet
中。 - 當
libAd
需要查詢 VIP 信息時,它會調用libNet
的getVipInfo()
方法,從而獲得最新的 VIP 數據。
- 當
- 通過使用
-
優勢與權衡:
- 優勢:這種方法利用了已有的依賴關系,不需要引入新的依賴或大幅度改變系統架構。
- 缺點:雖然實現簡單,但
libNet
的設計初衷可能并不是作為數據共享平臺,這樣的用途可能會使其承擔過多職責,違反單一職責原則,同時數據更新的及時性也無法得到保證。
通過這種方式,我們能在短時間內解決跨庫數據傳遞的問題,不過從長遠來看,仍需考慮更符合設計原則的重構方案,以保持代碼的清晰性和可維護性。
推薦方案:使用 app
作為中介
由于 app
本身依賴于 libAd
和 libVip
,所以我們可以在 app
層面處理這種數據傳遞。下面介紹具體實現步驟:
1. 為 libAd
添加接口
首先,為 libAd
新增一個接口,用于同步 libVip
的數據:
/*** libAd 同步 libVip 的數據* 如果需要同步其他無依賴關系的庫的數據,可以繼續新增方法*/
public interface LibAdDataListener {/*** @return 是否是 Vip*/boolean isVip();/*** @return 獲取當前 VIP 類型*/String getVipType();
}
2. 在 libAd
的管理類中新增方法
在 AdManager
類中添加以下方法,用于設置和獲取數據監聽器:
private LibAdDataListener dataListener;public AdManager setSharedDataListener(LibAdDataListener dataListener) {this.dataListener = dataListener;return this;
}public LibAdDataListener getSharedDataListener() {return dataListener;
}
3. 在 app
中實現數據監聽
在應用的 Application
類的初始化方法中,設置 LibAdDataListener
實現:
AdManager.getInstance(this).setSharedDataListener(new LibAdDataListener() {@Overridepublic boolean isVip() {// TODO: 調用 libVip 數據return false;}@Overridepublic String getVipType() {// TODO: 調用 libVip 數據return null;}
});
4. 在 libAd
中獲取信息
當 libAd
需要獲取 VIP 信息時,可以直接調用:
LibAdDataListener listener = AdManager.getInstance(context).getSharedDataListener();
通過這種方式,我們有效地解耦了 libAd
和 libVip
,同時利用 app
作為中介來實現數據共享。這種設計既避免了庫之間的直接依賴,也遵循了合適的設計原則,使得系統更加靈活和可維護。
- 相關文章 Android:lib庫之間互不依賴,怎么傳值?