組件自己提供Service Locator模式,用來降低組件的耦合度。
[Architecture] Singleton Locator
目的
組件自己提供Service Locator模式,用來降低組件的耦合度。
情景
在開發系統時,底層的Infrastructure Context、或是核心的Domain Context這些共用物件生成之後,會在系統的許多地方被使用。為了減少共用物件初始生成、參考傳遞所造成的困擾,可以在系統內套用Service Locator模式,提供統一的靜態參考點來生成、存取這些共用物件。
-
Service Locator參考資料
-
Service Locator物件結構
Service Locator模式確實減少共用物件初始生成、參考傳遞所造成的困擾,但在實作的過程中卻會發現Service Locator模式,很容易為系統中的組件引入額外相依性。以下列這個範例專案來說,Client物件經由ServiceLocator物件,取得DataContext物件在執行過程中存取資料。
-
物件圖
在實作的過程中為了能夠重用程式碼,通常會將ServiceLocator物件封裝為Infrastructure組件內容,而DataContext物件封裝成為Domain組件內容、Client物件則是封裝為Host組件。
-
組件圖
一般來說Infrastructure組件內會包含許多基礎物件,不會單純只封裝ServiceLocator物件。當這些基礎物件引用其他參考時,也就是間接的增加了Host組件的相依性、增加了Host組件對於其他組件的耦合。
-
組件圖
這時可以考慮將ServiceLocator物件設計為獨立組件,讓組件裡只包含一個物件以避免不必要的相依性。但是當這樣的設計一多的時候,很容易就會讓組件的設計過於破碎。
-
組件圖
為了降低組件耦合的問題,回過頭思考Client物件、DataContext物件、ServiceLocator物件三者之間的關係。會發現Client物件需要的是ServiceLocator物件所提供的物件生成、靜態參考等功能,而不是真的需要一個ServiceLocator物件。
這時開發人員可以將ServiceLocator物件所提供的物件生成、靜態參考等功能,建立在DataContext物件自己本身之上,透過DataContext物件自己提供物件生成、靜態參考等功能。也就是說經由這樣的設計,將ServiceLocator物件從系統中移除、也就是把Infrastructure組件從系統中移除,進而降低了Host組件的相依性、降低了Host組件對於其他組件的耦合。
-
組件圖
結構
-
物件圖
參與者
Service
-
提供自身服務功能。
-
提供自身靜態參考,用於參考定位、外部生成。
-
提供自身生成功能,用於內部生成。
Client
-
使用Context功能的物件。
-
外部生成的使用情景中,生成Context並且注入Context靜態參考。
合作方式
-
外部生成
-
內部生成
(為了簡化說明,Service生成模式採用直接建立的方式來示意。實際專案可以採用各種IoC Framework來做生成注入,或是套用各種Factory pattern,這些都能提高Service的重用性。)
實作
-
類別圖
-
Service
public partial class Service { // Locator private static Service _current; public static Service Current { get { if (_current == null) { _current = new Service("內部生成"); } return _current; } set { _current = value; } } } public partial class Service { // Constructors public Service(string message) { // Arguments this.Message = message; } // Properties public string Message { get; set; } // Methods public void Execute() { Console.WriteLine(this.Message); } }
-
外部生成
class Program { static void Main(string[] args) { // Init Init(); // Execute Service.Current.Execute(); Console.WriteLine(); // End Console.WriteLine("End..."); Console.ReadLine(); } static void Init() { // Service Service.Current = new Service("外部生成"); } }
-
內部生成
class Program { static void Main(string[] args) { // Init Init(); // Execute Service.Current.Execute(); Console.WriteLine(); // End Console.WriteLine("End..."); Console.ReadLine(); } static void Init() { // Service } }
(為了簡化說明,Service生成模式採用直接建立的方式來示意。實際專案可以採用各種IoC Framework來做生成注入,或是套用各種Factory pattern,這些都能提高Service的重用性。)
下載
範例程式碼:點此下載
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。