[原创]实例-少用单例及降低耦合

引言

我想就我个人开发时遇到的一些实际情况,与各位做一些分享,语言以c#、java为例,代码遵循语言编码规范

实例

本文以某.net客户端项目A为例,在项目A中,数据访问层存在如下多个服务模块

1、各服务内聚了数据处理逻辑,并提供简单的接口供上层业务逻辑调用

2、各个服务间存在相互调用的情况

为便于上层访问各数据服务,一些程序员会将每个服务都定位为单例,或许会习惯性的命名为XxxManager

服务间的应用,如服务A依赖服务B提供数据,不假思索的使用BSerivice.Instance.Xxx()获取数据

对于小型项目,这样做无可厚非,随着软件的复杂度的提升,这样的结构难免会造成维护上的苦难。过多全局实例,服务间的强耦合,自然散发出不佳的味道

那么如何改善,考虑如下两点

1、我不需要每一个服务都是单例类型

2、我不希望各个服务之间严重耦合,最好以接口来获取服务

少用单例&降低耦合

单例是常用且最基本的一种设计模式。然而,单例的作用相当于全局对象,应避免过度使用

采用如下设计

针对每个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程序集中以供复用)

解耦合往往会加倍你的类型数量,提升复杂度。

开发中应该注意保持代码的简单易于维护,使其在任何时候都易于重构,做到这点你的软件就已经具备很强的生命力了。

时间: 2024-10-08 10:24:21

[原创]实例-少用单例及降低耦合的相关文章

转--python 中写单例

原文地址 原文地址2 Python中的单例模式的几种实现方式的及优化 阅读目录(Content) 单例模式 实现单例模式的几种方式 1.使用模块 2.使用装饰器 3.使用类 4.基于__new__方法实现(推荐使用,方便) 5.基于metaclass方式实现 相关知识 实现单例模式 回到顶部(go to top) 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对

【Java】设计模型-五种单例模型

一. 什么是单例模式 只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计. 单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在. 单例模式有很多好处,它能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间: 能够避免由于操作多个实例导致的逻辑错误.如果一个对象有可能贯穿整个应用程序,而且起到了全局统一管理控制的作用,那么单例模式也许是一个值得考虑的选择. 二. 单例模式的特点 1. 单例模式只能有一个实例. 2. 单例类必

设计模式 之 单例

单例模式(Singleton Pattern) 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 最近一直在用VB.NET重构机房收费系统,在重构中就出现了一个这样的问题: 每点击一次充值的菜单,都会出现一个新的充值窗体.我就希望它要么不出现,出现也只出现一个.这个就和我们今天讲的单例模式有关系了. 大家都知道,世界上的所有事物都是独一无二的,也就是说没有哪两个事物是完全相同的.从这个角度来讲,每一个事物相对于自身都是单例的.我们今天所讲的单例设计模式则有所区别,它是针对某一类事物来说,只

scala学习手记14 - 单例对象

java中的单例模式都很熟悉了:简单地说就是一个类只能有一个实例.在scala中创建单例对象非常简单,创建类时使用object关键字替换class即可.因为单例类无法初始化,所以不能向它的主构造函数传递参数. 下面是一个单例的示例: class Marker(val color: String) { println("Creating " + this) override def toString(): String = "marker color " + colo

Objective-C设计模式——单例Singleton(对象创建)

单例 和其它语言的单例产不多,可以说是最简单的一种设计模式了.但是有几个点需要注意下,单例就是一个类只有一个实例. 所以我们要想办法阻止该类产生别的实例,一般语言中都会将构造函数写为private.但是OC中的函数并没有限定符,所以我们需要用一些小技巧来屏蔽这一点. 应用场景 类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法. 这个唯一的实例只能通过类的子类化进行扩展,而且扩展的对象不会破坏客户端代码. 注意 1.OC中单例的实例变量要定义在.m文件 2.OC中单例需要

struts2的action是多例,servlet是单例

struts2中action是多例的,即一个session产生一个action如果是单例的话,若出现两个用户都修改一个对象的属性值,则会因为用户修改时间不同,两个用户访问得到的 属性不一样,操作得出的结果不一样.举个例子:有一块布长度300cm,能做一件上衣(用掉100cm)和一件裤子(用掉200cm);甲和乙同时访问得到的 长度都是300cm,甲想做上衣和裤子,他先截取100cm去做上衣,等上衣做完再去做裤子,而乙这时正好也拿100cm去做上衣,那 好,等甲做完上衣再做裤子的时候发现剩下的布(

设计模式--单例

单例设计模式用来创建唯一的对象,有些时候我们只需要一个对象,如:线程池,缓存,对话框,注册表,日志对象,等等.这就需要单例设计模式来完成.不用多说,直接上代码.public class TestSingle { private static TestSingle single = null; private TestSingle(){} public static TestSingle getInstance(){ if(single==null){ single = new TestSingl

iOS单例详解

在开发中经常会用到单例设计模式,目的就是为了在程序的整个生命周期内,只会创建一个类的实例对象,而且只要程序不被杀死,该实例对象就不会被释放.下面我们来看看单例的概念.用途.如何创建,以便加深理解. 作用 在应用这个模式时,单例对象的类必须保证只有一个实例存在.许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为.比如在APP开发中我们可能在任何地方都要使用用户的信息,那么可以在登录的时候就把用户信息存放在一个文件里面,这些配置数据由一个单例对象统一读取,然后服务进程中的其他

1.单例设计模式

单例设计模式 概念: 单例模式是一种常见的设计模式多种,如懒汉.饿汉.登记式等 特点: 1.单例类只能有一个实例 2.单例类必须自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 饿汉式: 懒汉式一进内存就创建了实例 1 class Dog{ 2 private Dog(){} 3 //内部定义一个实例,供内部调用 4 private static Dog d = new Dog(); 5 //提供了一个访问该对象的方法. 6 public static Dog getDog(