引言
我想就我我的開發時遇到的一些實際狀況,與各位作一些分享,語言以c#、java爲例,代碼遵循語言編碼規範
實例
本文以某.net客戶端項目A爲例,在項目A中,數據訪問層存在以下多個服務模塊
一、各服務內聚了數據處理邏輯,並提供簡單的接口供上層業務邏輯調用
二、各個服務間存在相互調用的狀況
爲便於上層訪問各數據服務,一些程序員會將每一個服務都定位爲單例,或許會習慣性的命名爲XxxManager
服務間的應用,如服務A依賴服務B提供數據,不假思索的使用BSerivice.Instance.Xxx()獲取數據
對於小型項目,這樣作無可厚非,隨着軟件的複雜度的提高,這樣的結構不免會形成維護上的苦難。過多全局實例,服務間的強耦合,天然散發出不佳的味道
那麼如何改善,考慮以下兩點
一、我不須要每個服務都是單例類型
二、我不但願各個服務之間嚴重耦合,最好以接口來獲取服務
少用單例&下降耦合
單例是經常使用且最基本的一種設計模式。然而,單例的做用至關於全局對象,應避免過分使用
採用以下設計
針對每一個Service類型,分別定義對應的IXxxService接口類型,不要擔憂類型爆炸(類型/接口 數量激增),Service畢竟不足10個
僅存在一個單例類型ServicesManager,其組合各Service實例,上層直接以ServicesManager.Instance.XxxService獲取接口類型的服務對象
那麼如何下降服務間的耦合呢,見下圖
ServicesManger實現System.IServiceProvider接口,實現GetService方法,以做爲服務提供者
組合一個集合類型用做容器,字典_serviceMap,key爲Type,value爲service實例
總體代碼大體以下
class ServicesManager : IServiceProvider
{
private static readonly ServicesManager INSTANCE = new ServicesManager();
public static ServicesManager Instance
{
get { return INSTANCE; }
}
private readonly Dictionary<Type, object> _serviceMap = new Dictionary<Type, object>();
public void AddService<T>(T service)
{
_serviceMap.Add(typeof(T), service);
}
public object GetService(Type serviceType)
{
return _serviceMap[serviceType];
}
public void Init()
{
UserCenterService userCenterService = new UserCenterService(this);
userCenterService.Init();
AddService<IUserCenterService>(userCenterService);
// ...
}
}
在Init方法中依次初始化各個Service對象,構造方法中注意傳遞this參數(將最爲服務提供者),經過AddService泛型方法將各實例添加到容器中
每一個Service均從抽象類型ServiceBase派生,基類ServiceBase維護一個IServiceProvider類型的字段_serviceProvider,引用實際的ServicesManager對象
ServiceBase的實現大體以下
abstract class ServiceBase
{
private readonly IServiceProvider _serviceProvider;
protected ServerServiceBase(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected T GetService<T>() where T : class
{
return _serviceProvider.GetService(typeof(T)) as T;
}
}
在各Service內部,能夠使用方式以下獲取其餘Service實例
var realtimeDataService = GetService<IRealtimeDataService>();
realtimeDataService.xxxx
結語
這其實就是一個最基本的依賴注入實現,經過接口,各服務間獲得瞭解耦。對於上層業務邏輯而言,也不須要知道各個Service的具體實現,甚至能夠經過遠程訪問的方式,以接口的形式調用各類服務(實際上這個軟件正是這樣作的,一臺機器維護數據,提供數據層Service接口,多客戶端鏈接該機器查詢數據,全部接口定義放在Common程序集中以供複用)
解耦合每每會加倍你的類型數量,提高複雜度。
開發中應該注意保持代碼的簡單易於維護,使其在任什麼時候候都易於重構,作到這點你的軟件就已經具有很強的生命力了。