话说写代码已有数年,曾经花了很多时间,看了很多大牛的文章也是不能参透,日思夜想都没有理解的概念,通过不断的实践与学习,回过头来再看,总算有了一个清晰的理解与认识,也看到一句话说,最好的学习就是把别人教会,因此想把这些曾经我很难理解的知识以我认为最易理解的形式分享出来。

之所以把委托和IOC放在一起,是因为下文这一个场景可以解释这两个概念。

1)委托

这里只谈委托的使用场景,不谈那些令人烦恼的概念。

比如,你所参与的项目需要一个功能,需要实现在互联网上下载音频文件。这个时候,你要写一个下载类,下载完成后,还要实现播放、备份这两个操作。这个下载类是只有下载一个功能,至于播放和备份,是另外两个类需要做的事。

这种场景,用委托是最合适的了,也很利于以后的扩展,下载完成后,还可能有播放提示音、关机等等的操作。

至于.net里面的事件,也是这样用的,这里下载完成就相当于一个事件,很多框架里也是这样用的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace ConsoleApplication1
{
public delegate void DownloadFinish(string file);
class DownLoader
{
public DownloadFinish DownloadFinishHandler; public void Download()
{
Console.WriteLine("开始下载...");
Thread.Sleep();
Console.WriteLine("下载完成");
string downloadedfile = @"c:\fly.mp3";
if (DownloadFinishHandler != null)
{
DownloadFinishHandler(downloadedfile);
}
}
}
}

下载类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace ConsoleApplication1
{
class MusicPlayer
{
public void Play(string file)
{
Console.WriteLine("开始播放文件 " + file);
Thread.Sleep();
Console.WriteLine("播放文件完成");
}
}
}

音乐播放类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace ConsoleApplication1
{
class FileBak
{
public void Back(string file)
{
Console.WriteLine("开始备份文件"+file);
Thread.Sleep();
Console.WriteLine("备份文件完成");
}
}
}

文件备份类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//委托演示
var downloader = new DownLoader();
downloader.DownloadFinishHandler += new FileBak().Back;
downloader.DownloadFinishHandler += new MusicPlayer().Play;
downloader.Download();
Console.Read();
}
}
}

调用类

2)IOC(依赖注入)

这里设定的场景是,下载音乐,然后播放。

先看一下没有IOC时的写法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace ConsoleApplication2
{
class DownLoader
{
public void Download()
{
Console.WriteLine("开始下载...");
Thread.Sleep();
Console.WriteLine("下载完成");
string downloadedfile = @"c:\fly.mp3"; var player = new MusicPlayer();
player.Play(downloadedfile);
}
}
}

下载类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace ConsoleApplication2
{
class MusicPlayer
{
public void Play(string file)
{
Console.WriteLine("开始播放文件 " + file);
Thread.Sleep();
Console.WriteLine("播放文件完成");
}
}
}

音乐播放类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//无IOC演示
var downloader = new DownLoader();
downloader.Download();
Console.Read();
}
}
}

调用类

可以看到下载类和音乐播放类耦合了。

再看用构造函数注入后,也就是使用IOC后的写法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace ConsoleApplication3
{
class DownLoader
{
private IMusicPlayer musicPlayer; public DownLoader()
{ } public DownLoader(IMusicPlayer player)
{
musicPlayer = player;
} public void Download()
{
Console.WriteLine("开始下载...");
Thread.Sleep();
Console.WriteLine("下载完成");
string downloadedfile = @"c:\fly.mp3"; if (musicPlayer != null)
{
musicPlayer.Play(downloadedfile);
}
}
}
}

下载类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ConsoleApplication3
{
interface IMusicPlayer
{
void Play(string file);
}
}

音乐播放类接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace ConsoleApplication3
{
class MusicPlayer : IMusicPlayer
{
public void Play(string file)
{
Console.WriteLine("开始播放文件 " + file);
Thread.Sleep();
Console.WriteLine("播放文件完成");
}
}
}

音乐播放类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
//IOC演示
var player = new MusicPlayer();
var downloader = new DownLoader(player);
downloader.Download();
Console.Read();
}
}
}

调用类

这个时候,多了个一个接口,下载类在编译时依赖这个接口,实例化时,再把具体的类传给它。
2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。

所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。

文章源代码下载

委托、IOC全知道的更多相关文章

  1. 【死磕 Spring】----- IOC 之深入理解 Spring IoC

    在一开始学习 Spring 的时候,我们就接触 IoC 了,作为 Spring 第一个最核心的概念,我们在解读它源码之前一定需要对其有深入的认识,本篇为[死磕 Spring]系列博客的第一篇博文,主要 ...

  2. IOC 之深入理解 Spring IoC

    在一开始学习 Spring 的时候,我们就接触 IoC 了,作为 Spring 第一个最核心的概念,我们在解读它源码之前一定需要对其有深入的认识,本篇为[死磕 Spring]系列博客的第一篇博文,主要 ...

  3. C#语法之委托和事件

    从大学就开始做C#这块,也做C#几年了,最近又从ios转回.Net,继续做C#,之前也没有写博客的习惯,写博客也是从我做ios的时候开始的,现在既然又做回了.net,那就写点关于.Net的博客,可能在 ...

  4. IOC DI 专题

    IoC:Inversion of Control,控制反转DI:Dependency Injection,依赖注入 要理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁?依赖:谁依赖于谁?为什么 ...

  5. 实现一个自己的IOC

    实现一个自己的IOC package com.IocExample; import java.lang.reflect.Constructor; import java.lang.reflect.In ...

  6. Spring4学习回顾之路02—IOC&DI

    IOC&DI介绍 ●IOC:(Inversion of Control) :控制反转(反向获取资源) 其思想是反转资源获取的方向.传统的资源上查找方式要求组件向容器发起请求查找资源,作为回应, ...

  7. 【SpringBoot】 理解Spirng中的IOC原理

    前言 前文已经介绍了Spring Bean的生命周期,在这个周期内有一个重要的概念就是: IOC容器 大家也知道IOC是Sping 的重要核心之一,那么如何理解它呢,它又是产生什么作用呢?本文就IOC ...

  8. Spring IoC(一)bean实例化和依赖注入

    1.IoC容器概述 IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入. 所谓 IOC ,就 ...

  9. Spring入门之一-------实现一个简单的IoC

    一.场景模拟 public interface Human { public void goHome(); } Human:人类,下班了该回家啦 public interface Car { void ...

随机推荐

  1. 通过sougou输入法,解决卡在Setup Wizard(小绿人)界面

    本人使用海信EG900手机(安卓2.3.5,已root),为了使用google的服务,先后手动复制和CWM recovery刷入google服务包(gapps-gb-20110828-signed.z ...

  2. IT励志与指导文章合集(链接)

    乔布斯在斯坦福大学的演讲 http://www.cnblogs.com/tryingx/p/3715886.html 程序员的8个级别 http://www.cnblogs.com/tryingx/p ...

  3. 周末被一个BUG折腾的欲仙欲死

    有一个应用场景:从网上得到大量的文字信息,保存到本地. 因为不停地获取文章,导致本地存储很快就变大.所以想到了简单地压缩. 网上找了一段压缩的代码: +(NSData*)zipContent:(NSS ...

  4. 查看哪些表的哪些列含有指定字符串(如‘andy’存在哪些表的哪些列中)

    -- 查看表中列含有指定字符.SQL> select * from demo1;NAME                                   ID---------------- ...

  5. maven 私服搭建

    1,下载 https://sonatype-download.global.ssl.fastly.net/nexus/oss/nexus-2.14.2-01-bundle.zip 2,解压 3,安装 ...

  6. Amazon验证码机器算法识别

    Amazon验证码识别 在破解Amazon的验证码的时候,利用机器学习得到验证码破解精度超过70%,主要是训练样本不够,如果在足够的样本下达到90%是非常有可能的. update后,样本数为2800多 ...

  7. LoadRunner简介

    LoadRunner是什么 LoadRunner是一个性能测试工具,它最初是Mercury公司的产品,后背HP收购. LoadRunner常用来做什么 l 验证某系统在某环境下是否满足性能需求. l  ...

  8. 读取其他软件listview控件的内容

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. css3 em rem等单位的区别

    px:绝对单位,页面按精确像素展示 em:相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算(浏览器默认字体是16px),整个页面内1em不是一个固定的值. rem:相对 ...

  10. zepto.js使用前注意

    API:http://www.css88.com/doc/zeptojs_api/ 一.建议:不要从官网下载,而是从 Github 下载了源代码之后自己 Build 一个版本,这样你可以自行挑选适合的 ...