Middle+
Welke mechanismen helpen het principe van afhankelijkheidsomkering te handhaven?
sobes.tech AI
Antwoord van AI
Het principe van afhankelijkheidsomkering (Dependency Inversion Principle - DIP) wordt nageleefd door verschillende onderling verbonden mechanismen:
-
Abstracties:
- Interfaces en abstracte klassen definiëren contracten, niet concrete implementaties. Hoog-niveau modules vertrouwen op deze abstracties, niet op concrete klassen van laag-niveau.
-
Dependency Injection (DI):
- In plaats van dat een klasse zijn afhankelijkheden direct creëert, worden deze van buitenaf doorgegeven. Dit maakt het gemakkelijk om afhankelijkheidsimplementaties te vervangen zonder de code van de klasse te wijzigen.
- C# syntax voor injectie via de constructor:
public class HighLevelModule { private readonly ILowLevelDependency _dependency; // Afhankelijkheid van de abstractie public HighLevelModule(ILowLevelDependency dependency) // Injectie via constructor { _dependency = dependency; } public void PerformAction() { _dependency.Execute(); // Gebruik van afhankelijkheid via abstractie } } - C# syntax voor injectie via eigenschap:
public class AnotherHighLevelModule { public ILowLevelDependency Dependency { get; set; } // Injectie via eigenschap public void PerformAction() { Dependency?.Execute(); // Gebruik van afhankelijkheid via abstractie } } - C# syntax voor injectie via methode:
public class YetAnotherHighLevelModule { public void PerformAction(ILowLevelDependency dependency) // Injectie via methode { dependency.Execute(); // Gebruik van afhankelijkheid via abstractie } }
-
IoC-containers (Inversion of Control Containers):
- Frameworks die het proces van afhankelijkheidsbeheer en injectie automatiseren. Ze maken instanties van klassen en lossen hun afhankelijkheden op volgens geconfigureerde regels.
- Voorbeeld van gebruik van een populaire IoC-container (bijvoorbeeld, StructureMap):
// Registratie van afhankelijkheid // container.Configure(cfg => // { // cfg.For<ILowLevelDependency>().Use<ConcreteLowLevelDependency>(); // Registratie van abstractie en concrete implementatie // cfg.For<HighLevelModule>().Use<HighLevelModule>(); // }); // Verkrijg een instantie van de klasse met opgeloste afhankelijkheden // var highLevelModule = container.GetInstance<HighLevelModule>(); // highLevelModule.PerformAction();
-
Fabrieken:
- Klassen die verantwoordelijk zijn voor het maken van instanties van andere klassen. Ze kunnen details van het maken van concrete implementaties verbergen en abstracties teruggeven.
- C# syntax voor voorbeeldgebruik van een fabriek:
public interface ILowLevelDependencyFactory { ILowLevelDependency Create(); } public class LowLevelDependencyFactory : ILowLevelDependencyFactory { public ILowLevelDependency Create() { return new ConcreteLowLevelDependency(); // Maken van een concrete implementatie } } public class HighLevelModuleWithFactory { private readonly ILowLevelDependency _dependency; public HighLevelModuleWithFactory(ILowLevelDependencyFactory factory) // Injectie van de fabriek { _dependency = factory.Create(); // Gebruik van de fabriek om afhankelijkheid te maken } public void PerformAction() { _dependency.Execute(); } }
-
Wet van Demeter (Law of Demeter):
- Hoewel geen direct mechanisme van DIP, vermindert het volgen van dit principe (alleen praten met "je directe vrienden") vaak de directe afhankelijkheden en vergemakkelijkt het toepassen van DIP.