648
技術社區[雲棲]
設計模式——控製反轉&依賴注入
一、控製反轉:
從簡單的代碼示例入手:
/// <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