一步一步造个Ioc轮子目录

一步一步造个IoC轮子(一):Ioc是什么
一步一步造个IoC轮子(二):详解泛型工厂
一步一步造个IoC轮子(三):构造基本的IoC容器

详解泛型工厂

既然我说IoC容器就是一个豪华版工厂,自动化装配的工厂,那我们就从工厂入手吧,先造个工厂,然后升级成IoC容器

首先我们来写一个最最最简单的抽象工厂类,还是以前一篇的短信为例

    public class SMSFactory
{
public static ISMS Get()
{
return new XSMS();
}
}

然后我们琢磨着怎么把这个XSMS不要写死在代码上,嗯加一个注册方法,把SMS对象传进去

    public class SMSFactory
{
static ISMS _sms;
public static ISMS Get()
{
return _sms;
}
public static void Reg(ISMS sms)
{
_sms = sms;
}
}

这个代码分离了业务对XSMS的依赖,但依然要在程序启动时注册一个ISMS实现对象进去如:SMSFactory.Reg(new XSMS());

我们再琢磨着这个工厂越写越复杂,还只能用来做短信,能不能搞成通用呢,嗯,改成泛型吧

    public class Factory<T> where T:class
{
static T _obj;
public static T Get()
{
return _obj;
}
public static void Reg(T obj)
{
_obj = obj;
}
}

嗯,搞出一个好简单的泛型工厂了,我们再琢磨一下,这东西要在系统启动就传new好的对象进去,有点不科学啊,能不能让工厂自己new 呢,试试吧

    public class Factory<T> where T:class,new()
{
public static T Get()
{
return new S(); //晕了,S的从哪里取呢
}
public static void Reg<S>() where S:T
{
//怎么把S(继承类)保存下来呢???这下头痛了
}
}

貌似不行哦,我们怎么保存继承类的信息在这个工厂里呢,聪明的前人想到了一个方法,用一个含S信息的对象创建不就行了,这个对象又继承了一个含Create方法的接口,Get的时候调用这个对象的Create的方法

    public class Factory<T> where T : class
{
static ICreate creater;
interface ICreate
{
T Create();
}
class Creater<U> : ICreate where U : T, new()
{
public T Create()
{
return new U();
}
}
public static T Get()
{
//调用creater对象的Create方法实际上相当于调用了Creater<U>的new U()
return creater.Create();
}
public static void Reg<S>() where S : T, new()
{
//在这里,我们把S的信息保存到了creater对象上
creater = new Creater<S>();
}
}

完美啊,用一个临时的对象保存了继承类的信息,这样就可以在工厂类注册继承类进去了,回到上篇小黄的改来改去的SMS模块问题,我们也可以用这个泛型工厂解决掉业务的依赖问题了var sms = Factory<ISMS>.Get();只是要在启动的配置里注册上实现类

我们能不能再扩展一下,让他支持单例呢,答案当然是yes了,只要对Creater改造一下

    public class Factory<T> where T : class
{
static ICreate creater;
interface ICreate
{
T Create();
}
class Creater<U> : ICreate where U : T, new()
{
public T Create()
{
return new U();
}
}
class SingletonCreater<U> : ICreate where U : T, new()
{
T instance;
object locker = new object();
public T Create()
{
//使用双检锁
if (instance == null)
{
lock (locker)
{
if (instance == null)
{
Interlocked.Exchange(ref instance, new U());
}
}
}
return instance;
}
}
public static T Get()
{
return creater.Create();
}
public static void Reg<S>() where S : T, new()
{
creater = new Creater<S>();
}
public static void RegSingleton<S>() where S : T, new()
{
creater = new SingletonCreater<S>();
}
}

哟,真行,不过有锁,能不能去掉锁呢,yes,我们来用静态readonly魔法,创建一个内部类,只有访问这个内部类时这个对象才会被创建,而且是线程安全的

    public class Factory<T> where T : class
{
static ICreate creater;
interface ICreate
{
T Create();
}
class Creater<U> : ICreate where U : T, new()
{
public T Create()
{
return new U();
}
}
class SingletonCreater<U> : ICreate where U : T, new()
{
class InstanceClass
{
public static readonly T Instance = new U();
}
public T Create()
{
return InstanceClass.Instance;
}
}
public static T Get()
{
return creater.Create();
}
public static void Reg<S>() where S : T, new()
{
creater = new Creater<S>();
}
public static void RegSingleton<S>() where S : T, new()
{
creater = new SingletonCreater<S>();
}
}

果然黑魔法,接下来我们再魔改一下这个泛型工厂,让他支持传入参数,其实也很简单,用个字典保存一下key和creater的对应关系就是了

    public class Factory<T> where T : class
{
interface ICreate
{
T Create();
}
class Creater<U> : ICreate where U : T, new()
{
public T Create()
{
return new U();
}
}
class SingletonCreater<U> : ICreate where U : T, new()
{
class InstanceClass
{
public static readonly T Instance = new U();
}
public T Create()
{
return InstanceClass.Instance;
}
}
#region 无参数的
static ICreate creater;
public static T Get()
{
return creater.Create();
}
public static void Reg<S>() where S : T, new()
{
creater = new Creater<S>();
}
public static void RegSingleton<S>() where S : T, new()
{
creater = new SingletonCreater<S>();
}
#endregion #region 有参数的
static IDictionary<string, ICreate> creaters = new System.Collections.Concurrent.ConcurrentDictionary<string, ICreate>();
public static T Get(string key)
{
ICreate ct;
if (creaters.TryGetValue(key, out ct))
return ct.Create();
throw new Exception("未注册");
}
public static void Reg<S>(string key) where S : T, new()
{
creaters[key] = new Creater<S>();
}
public static void RegSingleton<S>(string key) where S : T, new()
{
creaters[key] = new SingletonCreater<S>();
}
#endregion
}

好了,泛型工厂详解和魔改完毕,支持注册单例,测试一下,完美,是不是已经有了IoC的味道了,下一步我们就再魔改这个工厂,改造为可以从配置读取及优化从参数的获取的性能


我不是想引起战争,但真泛型确是.net的魔法,java这样搞是不行的,java只能反射了,接近new的性能就是.net真泛型所赋予的

代码下载,用VS2015 update3写的,不用.net core的可以直接复制代码出来

一步一步造个IoC轮子(二),详解泛型工厂的更多相关文章

  1. 一步一步造个IoC轮子(一):IoC是什么

    一步一步造个Ioc轮子目录 一步一步造个IoC轮子(一):IoC是什么 一步一步造个IoC轮子(二):详解泛型工厂 一步一步造个IoC轮子(三):构造基本的IoC容器 前言 .net core正式版前 ...

  2. 一步一步造个IoC轮子(三):构造基本的IoC容器

    一步一步造个Ioc轮子目录 一步一步造个IoC轮子(一):Ioc是什么 一步一步造个IoC轮子(二):详解泛型工厂 一步一步造个IoC轮子(三):构造基本的IoC容器 定义容器 首先,我们来画个大饼, ...

  3. Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程

    上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...

  4. Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

    上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...

  5. Spring IoC @Autowired 注解详解

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 我们平时使用 Spring 时,想要 依赖 ...

  6. Spring IoC 公共注解详解

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 什么是公共注解?公共注解就是常见的Java ...

  7. Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计

    在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解.本文将帮助你站在设计者的角度去看IOC最顶层的结构设计.@pdai Spring框架系列(6) - Spring IOC实现原理详解 ...

  8. Spring IoC createBean 方法详解

    前言 本篇文章主要分析 Spring IoC 的 createBean() 方法的流程,以及 bean 的生命周期. 下面是一个大致的流程图: 正文 AbstractAutowireCapableBe ...

  9. Spring IoC getBean 方法详解

    前言 本篇文章主要介绍 Spring IoC 容器 getBean() 方法. 下图是一个大致的流程图: 正文 首先定义一个简单的 POJO,如下: public class User { priva ...

随机推荐

  1. 【Z10】引水入城

    [题目链接]:http://noi.qz5z.com/viewtask.asp?id=z10 [题解] 对于第一问:从最上面那m个格子开始进行广搜就可以了: 然后看一下最下面那一行有没有被全部覆盖; ...

  2. 解决Eclipse 启动后总是Building WorkSpace(sleeping)

    打开eclipse后eclipse总是在Building WorkSpace(sleeping),我的解决方案是,Project -> Building AutoMatically关闭就好了,以 ...

  3. 【u017】请柬

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院, ...

  4. js如何实现动态点击改变单元格颜色?

    js如何实现动态点击改变单元格颜色? 一.总结 1.通过table的rows属性,遍历表格所有行,然后通过cells属性,遍历每一行中的单元格. 2.遍历的过程中,动态的为每一个单元格定义单击事件,改 ...

  5. js实现去文本换行符小工具

    js实现去文本换行符小工具 一.总结 一句话总结: 1.vertical属性使用的时候注意看清定义,也注意父元素的基准线问题.vertical-align:top; 2.获取textareaEleme ...

  6. iOS 9和xcode7设置

    升级了Xcode7各种问题来了,折腾两天 一.Xcode7  http适配设置 1.大部分社交平台接口不支持https协议. 2.大部分社交平台SDK不支持bitcode. 3.添加Scheme白名单 ...

  7. 【t067】补充装备

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] Mini进入洞口前自然要先来到镇里的装备店买些装备.买每件装备都需要付出一定的体力点,同时也会获得一定 ...

  8. tomcat 去除端口和项目名/使用域名访问/修改超链接为IP地址

    1.打开tomcat/conf/server.xml 在host标签中加入 <Context  docBase="项目名" path="" reloada ...

  9. java phoenix 连接hbase

    <dependency> <groupId>org.apache.phoenix</groupId> <artifactId>phoenix-core& ...

  10. DDoS ATTACK PROCESSING APPARATUS AND METHOD IN OPENFLOW SWITCH

    An OpenFlow switch in an OpenFlow environment includes an attack determination module to collect sta ...