One of the disadvantages that I have seen of using Service Locator type patterns is usually the generation of garbage every time it is called, generating poor performance if high utilization is reached. This is because many times the service is searched using the Type type, forcing you to do things like typeof(T).
This is a typical example of a Service Locator:
usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingUniFlux;usingUnityEngine;publicclassServiceLocator{privatestaticreadonlyDictionary<Type,object> services =newDictionary<Type,object>();publicstaticvoidRegisterService<T>(T service) {var type =typeof(T); // Look here, typeof causing garbageif (!services.ContainsKey(type)) {services.Add(type, service); } }publicstaticTGetService<T>() {var type =typeof(T); // Look here, typeof causing garbageif (services.ContainsKey(type)) {return (T)services[type]; // look here, (T) making explicit convertions }thrownewException($"Service of type {type} not registered."); }}classExample_A:Monobehaviour,IDataService{voidAwake() { // GenerateServiceLocator.RegisterService<IDataService>(this); }voidIDataService.SaveData(string data) { // etc... }}classExample_B:Monobehaviour{voidStart() { // Getting the instances..var dataService =ServiceLocator.GetService<IDataService>(); // Using itdataService.SaveData("Sample data"); }}
With UniFlux you can not only optimize the way information is treated, but you can even choose the way you want to interact with it.
Now let's do an example using UniFlux as Service Locator:
usingUniFlux;usingUnityEngine;classExample_A:MonoFlux,IDataService{ [MethodFlux(nameof(IDataService))] IDataServiceGet_IDataService_ExampleMethod() =>this;voidIDataService.SaveData(string data) { // etc... }}classExample_B:Monobehaviour{voidStart() { var dataService =nameof(IDataService).Dispatch<IDataService>(); // Using itdataService.SaveData("Sample data"); }}
In this example we can do the same treatment without having to lose performance in our execution, this is one way to do it but you can do it in different ways
You could even deal directly with the method ignoring the need for the interface: