引言
我想就我我的开发时遇到的一些实际状况,与各位作一些分享,语言以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程序集中以供复用)
解耦合每每会加倍你的类型数量,提高复杂度。
开发中应该注意保持代码的简单易于维护,使其在任什么时候候都易于重构,作到这点你的软件就已经具有很强的生命力了。