設計模式——控製反轉&依賴注入
一、控製反轉:
從簡單的代碼示例入手:
/// <summary> /// 郵件服務類 /// </summary> public class EmailService { public string SendMessage() { return "發送通知郵件"; } } /// <summary> /// 郵件通知類 /// </summary> public class NotifycationSystem { private EmailService service; public NotifycationSystem() { service = new EmailService(); //郵件通知類必須精確的知道創建和使用了哪種類型的服務,此處高耦合了。 } public string InterestingEventHappened() { return service.SendMessage(); } }共兩個類,一個郵件服務類,一個郵件通知類,郵件通知類依賴於郵件服務類。郵件通知類必須精確的知道創建和使用了哪種類型的服務,此處高耦合了。
改進一:在兩代碼塊中引入抽象層,提取接口。
/// <summary> /// 郵件服務接口 /// </summary> public interface IMessageService { string SendMessage(); } /// <summary> /// 郵件服務類 /// </summary> public class EmailService : IMessageService { public string SendMessage() { return "發送通知郵件"; } } /// <summary> /// 郵件通知類 /// </summary> public class NotifycationSystem { private IMessageService service;//郵件通知類保存服務實現的接口 public NotifycationSystem() { service = new EmailService(); } public string InterestingEventHappened() { return service.SendMessage(); } }上麵將依賴具體實現改為了依賴接口,減少了部分耦合。但是郵件服務類還是在郵件通知類內實例化的,也就是說郵件通知類還是要完全知道郵件服務類的具體細節。
改進二:將選擇抽象實現的責任移到服務消費者類的外部。
/// <summary> /// 第二層抽象: 服務定位器 /// </summary> public interface IServiceLocator { IMessageService GetMessageService(); } /// <summary> /// 第一層抽象:郵件服務接口 /// </summary> public interface IMessageService { string SendMessage(); } /// <summary> /// 郵件服務類 /// </summary> public class EmailService : IMessageService { public string SendMessage() { return "發送通知郵件"; } } /// <summary> /// 郵件通知類 /// </summary> public class NotifycationSystem { private IMessageService service;//郵件通知類保存服務實現的接口。 public NotifycationSystem(IServiceLocator locator) { service = locator.GetMessageService();//實現依賴關係被轉移到類外。 } public string InterestingEventHappened() { return service.SendMessage(); } }擴展一:弱類型服務定位器。
/// <summary> /// 第二層抽象: 服務定位器 /// </summary> public interface IServiceLocator { object GetService(Type serviceType); } /// <summary> /// 第一層抽象:郵件服務接口 /// </summary> public interface IMessageService { string SendMessage(); } /// <summary> /// 郵件服務類 /// </summary> public class EmailService : IMessageService { public string SendMessage() { return "發送通知郵件"; } } /// <summary> /// 郵件通知類 /// </summary> public class NotifycationSystem { private IMessageService service;//郵件通知類保存服務實現的接口。 public NotifycationSystem(IServiceLocator locator) { service = (IMessageService)locator.GetService(typeof(IMessageService));//實現依賴關係被轉移到類外。 } public string InterestingEventHappened() { return service.SendMessage(); } }
弱類型服務定位器使得這種模式更加靈活,因為他允許請求任意類型的服務類型。采用Type類型的參數,並返回一個非類型化的示例,也就是一個object類型對象。
擴展二:泛型方法。
/// <summary> /// 第二層抽象: 服務定位器 /// </summary> public interface IServiceLocator { T GetService<T>();//泛型接口 object GetService(Type serviceType); } /// <summary> /// 第一層抽象:郵件服務接口 /// </summary> public interface IMessageService { string SendMessage(); } /// <summary> /// 郵件服務類 /// </summary> public class EmailService : IMessageService { public string SendMessage() { return "發送通知郵件"; } } /// <summary> /// 郵件通知類 /// </summary> public class NotifycationSystem { private IMessageService service;//郵件通知類保存服務實現的接口。 public NotifycationSystem(IServiceLocator locator) { service = locator.GetService<IMessageService>();//實現依賴關係被轉移到類外。 } public string InterestingEventHappened() { return service.SendMessage(); } }泛型方法,讓依賴反轉代碼看上去更加高效優雅。
二、依賴注入:
1.構造函數注入:
/// <summary> /// 郵件通知類 /// </summary> public class NotifycationSystem { private IMessageService _service; public NotifycationSystem(IMessageService service)//構造函數注入 { _service = service; } public string InterestingEventHappened() { return _service.SendMessage(); } }2.屬性注入:
/// <summary> /// 郵件通知類 /// </summary> public class NotifycationSystem { private IMessageService MessageService { get; set; } public string InterestingEventHappened() { if (MessageService == null) { throw new InvalidOperationException("服務類型為賦值!"); } return MessageService.SendMessage(); } }
最後更新:2017-04-02 16:48:14