说IoC之前,我们先来说个很简单业务模型
1.保存系统日志到物理文件上
这个只要定义个ILog接口,并由FileLog类去具体实现即可。
View Code
1 public class LogInfo 2 { 3 public string UserId { get; set; } 4 5 public string IP { get; set; } 6 7 public string Content { get; set; } 8 9 public DateTime Time { get; set; } 10 } 11 12 13 public interface ILog 14 { 15 void Save(LogInfo info); 16 } 17 18 public class FileLog : ILog 19 { 20 public virtual void Save(LogInfo info) 21 { 22 Console.WriteLine("the log had been save in file"); 23 } 24 }
客户端调用如下。
View Code
1 public void SaveFileLog() 2 { 3 ILog log = new FileLog(); 4 LogInfo info = new LogInfo(); 5 info.UserId = "one@gmail.com"; 6 info.IP = "192.168.1.1"; 7 info.Content = "user login"; 8 9 log.Save(info); 10 }
但是,现在如果需求有增加了呢?
2.保存到数据库呢?
嗯,在开个类不就得了?
View Code
1 public class DBLog : ILog 2 { 3 public void Save(LogInfo info) 4 { 5 Console.WriteLine("the log had been save in db"); 6 } 7 }
至于客户端的调用,修改下也就可以了
View Code
1 public void SaveDBLog() 2 { 3 ILog log = new FileLog(); 4 LogInfo info = new LogInfo() 5 { 6 UserId = "one@gmail.com", 7 IP = "192.168.1.1", 8 Content = "user login" 9 }; 10 11 log.Save(info); 12 }
到这边事情好像都OK了,But,有没有更好的代码组织方式呢?
我讨厌在客户端这边一直写重复的代码(调用接口实例)。
那么我们是不是可以这样写呢?
View Code
1 public class LogService 2 { 3 public ILog Log { get; private set; } 4 5 public LogInfo Info { get; private set; } 6 7 8 public LogService(ILog log,LogInfo info) 9 { 10 this.Log = log; 11 this.Info = info; 12 } 13 14 public void Save() 15 { 16 this.Log.Save(this.Info); 17 } 18 } 19 20 public class Client 21 { 22 public void SaveLog() 23 { 24 LogInfo info = new LogInfo(); 25 info.UserId = "one@gmail.com"; 26 info.IP = "192.168.1.1"; 27 info.Content = "user login"; 28 29 ILog log = new FileLog(); 30 31 LogService service = new LogService(log, info); 32 33 service.Save(); 34 } 35 }
似乎看起来,貌似还不错嘛。但是还能不能更好呢?
毕竟,保存日志的介质在不同场景会有不同需求,这个时候,我们做移植时还要修改源代码,这违反了OCP原则
这个时候,我们可以利用反射来创建具体接口实例。
总结下:
IoC主要目的是松散耦合。
具体是,在对象外部通过容器创建维护对象依赖的对象,并通过参数来传递。
因为对象依赖的对象总是要有地方进行new(创建)的,而这步动作通过个容器来做。
这个容器应有很多实现方式,在Spring框架中,应该是利用反射+Xml配置文件来实现(这点不确定,只是猜测)