DI Anti Patterns - Service Locator
前言: 在前一篇的 Anti-Pattern 中我們介紹了最經典的反模式:Control Freak 。而在這篇我們要介紹的另外一個常見的反模式可以說是他的進化版本,尤其是這個模式是知名的架構師 Martin Fowler 提出的。不過在數年後有人挑戰了這個想法,該文章的討論串比正文還要長,但思辨的過程還是值得一看。 常見類型 Anti-pattern Description Control Freak 依賴反轉(Inversion of Control)的對立面,直接控制實體 Service Locator 使用一個內隱服務提供依賴給呼叫端 Ambient Context 使用靜態存取子,提供單一的依賴 Constrained Construction 讓建構子有一個特定的方法簽章 Service Locator 定義 是一種軟體開發中的設計模式,通過一個集中註冊表(通常會是 Singleton)來處理請求並返回處理特定任務所需的必要訊息。最常見的實做方式通常就是利用 Static Factory 來實做這個註冊表。而系統中可以在系統進入點以外的地方呼叫這個註冊表的方法取得指定的實做。 表準案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class HomeController : Controller { public HomeController() { } public ViewResult Index() { IProductService service = Locator.GetService<IProductService>(); var products = service.GetProducts(); return this.View(products); } } 1 2 3 4 5 6 7 8 9 10 11 public class ProductService : IProductService { private readonly IProductRepository repository; public ProductService() { this.repository = Locator.GetService<IProductRepository>(); } public IEnumerable<Product> GetProducts() { return this.repository.GetProducts(); } } 這邊可以看到當要使用 IProductService 時,就呼叫註冊表的方法來取得實做,但這個依賴關係因為不是在建構時給予因此從外部會不容易知道他們兩者之間會有這樣的關係存在。另外這個作法同樣也會遇到 Static Factory 會遇到的問題,只是 Service Locator 將原本呼叫與依賴關係建立的那一層做了一個包裝。原本的 Static Factory 會與實做相同介面的類別緊緊的綁在一個 Factory 類別中,而包裝起來之後變成所有類型的依賴與實做會都綁在 Service Locator 這個類別裡,它變得與更多依賴有關。同時,在使用上每個需要取得依賴的地方都需要能存取 Service Locator 。 ...