委托、IOC全知道
话说写代码已有数年,曾经花了很多时间,看了很多大牛的文章也是不能参透,日思夜想都没有理解的概念,通过不断的实践与学习,回过头来再看,总算有了一个清晰的理解与认识,也看到一句话说,最好的学习就是把别人教会,因此想把这些曾经我很难理解的知识以我认为最易理解的形式分享出来。
之所以把委托和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全知道的更多相关文章
- 【死磕 Spring】----- IOC 之深入理解 Spring IoC
在一开始学习 Spring 的时候,我们就接触 IoC 了,作为 Spring 第一个最核心的概念,我们在解读它源码之前一定需要对其有深入的认识,本篇为[死磕 Spring]系列博客的第一篇博文,主要 ...
- IOC 之深入理解 Spring IoC
在一开始学习 Spring 的时候,我们就接触 IoC 了,作为 Spring 第一个最核心的概念,我们在解读它源码之前一定需要对其有深入的认识,本篇为[死磕 Spring]系列博客的第一篇博文,主要 ...
- C#语法之委托和事件
从大学就开始做C#这块,也做C#几年了,最近又从ios转回.Net,继续做C#,之前也没有写博客的习惯,写博客也是从我做ios的时候开始的,现在既然又做回了.net,那就写点关于.Net的博客,可能在 ...
- IOC DI 专题
IoC:Inversion of Control,控制反转DI:Dependency Injection,依赖注入 要理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁?依赖:谁依赖于谁?为什么 ...
- 实现一个自己的IOC
实现一个自己的IOC package com.IocExample; import java.lang.reflect.Constructor; import java.lang.reflect.In ...
- Spring4学习回顾之路02—IOC&DI
IOC&DI介绍 ●IOC:(Inversion of Control) :控制反转(反向获取资源) 其思想是反转资源获取的方向.传统的资源上查找方式要求组件向容器发起请求查找资源,作为回应, ...
- 【SpringBoot】 理解Spirng中的IOC原理
前言 前文已经介绍了Spring Bean的生命周期,在这个周期内有一个重要的概念就是: IOC容器 大家也知道IOC是Sping 的重要核心之一,那么如何理解它呢,它又是产生什么作用呢?本文就IOC ...
- Spring IoC(一)bean实例化和依赖注入
1.IoC容器概述 IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入. 所谓 IOC ,就 ...
- Spring入门之一-------实现一个简单的IoC
一.场景模拟 public interface Human { public void goHome(); } Human:人类,下班了该回家啦 public interface Car { void ...
随机推荐
- 转载《Android Adapter简单总结》
1.概念 Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带.在常见的View(List View,Grid View)等地方都需要用到Adapter.如下 ...
- js代码实现下拉菜单
效果 js代码: <script type="text/javascript"> function ShowSub(li) {//函数定义 var subMenu = ...
- 创建js对象的属性和方法
按照如下的创建对象的方法,可以节省内存.记录一下方便日后使用 <!Doctype html><html> <head> <title></titl ...
- js中substr,substring,indexOf,lastIndexOf,split 的用法
1.substr substr(start,length)表示从start位置开始,截取length长度的字符串. var src="images/off_1.png";alert ...
- Win8.1离线安装.NET3.5
Win8.1离线安装.NET3.5 dism.exe /online /enable-feature /featurename:NetFX3 /Source:H:\sources\sxs 其中H为盘符 ...
- compile vim with lua & python support
vim在macosx 10.9默认没有带lua和python支持,因为装的有些插件是lua写的,有些是python写的,运行不起来,于是决定自己编译一个,下载vim源码,执行以下命令就可以编译vim: ...
- clang编译器简介
本文部分内容引用: 中文维基百科. 结构化编译器前端--clang介绍. 什么是clang编译器? clang是LLVM编译器工具集的一个用于编译C.C++.Objective-C的前端.LLVM项目 ...
- 路由 - ASP.NET MVC 4 系列
软件开发人员常常对一些细小的细节问题倍加关注,由其在考虑源代码的质量和结构时更是如此.因此,当遇到大部分使用 ASP.NET 技术构建的站点,使用如下的 URL 地址时,可能会有些奇怪: ...
- Sql server 备份还原后出现“受限制用户”问题
http://jingyan.baidu.com/article/eb9f7b6dcbf1ea869264e856.html SQL数据库作备份和还原操作几乎是日常性事务了.但某次在对Sql Serv ...
- jquery之文档操作
append(content|fn) 向每个匹配的元素内部添加内容(元素内部) appendTo(content) 把所有匹配的元素追加到另一个指定的元素中(元素内部) prepend(content ...