委托、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 ...
随机推荐
- js中toString和valueOf方法的区别
toString 方法 返回对象的字符串表示形式. 语法:objectname.toString([radix]) objectname 必需.要为其搜索字符串表示形式的对象. radix 可选.为将 ...
- Android——黑名单
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- 【转载】Chaotic Time-Series Prediction
原文地址:https://cn.mathworks.com/help/fuzzy/examples/chaotic-time-series-prediction.html?requestedDomai ...
- 使用subclass UIActivity的方案来分享图片
IOS6开始, 系统提供了UIActivityViewController, 对图片,文字,url进行相关的操作. 对于缺乏UI设计师的开发来说, 使用它进行轻量级的分享是很好的选择. 最大的缺点是自 ...
- 【java规则引擎】之Drools之Rete算法
一:规则引擎--->规则引擎的核心是Pattern Matcher(模式匹配器).不管是正向推理还是反向推理,首先要解决一个模式匹配的问题.--->对于规则的模式匹配,可以定义为: 一个规 ...
- IO:File类(java.io.File)
public class File extends Object implements Serializable, Comparable<File> 构造方法: public File(S ...
- tomcat building
https://tomcat.apache.org/tomcat-7.0-doc/building.html https://tomcat.apache.org/tomcat-7.0-doc/BUIL ...
- MAC的终端命令
今天小研究了一下MAC的终端命令,主要为了方便调试程序用,XCODE用不来啊... 在这里记下..防止丢失 pwd 当前工作目录 cd(不加参数) 进root cd(folder) 进入文件夹 cd ...
- int.Parse()、int.TryParse()和Convert.ToInt32()的区别
1:int.Parse(一个参数) 此参数必须满足: 1 只能是字符串: 2 只能是 “整型” 字符串,即各种整型ToString()之后的形式,也不能为浮点型. 2:int.TryPa ...
- linux下vi命令修改文件及保存的使用方法
进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi n filename :打开文件,并将光标置于第n行首 vi filename :打开文件,并将光标置于一行首 v ...