L'ambito membro non risolve completamente il problema
Anche se dichiari GeometrySplitter
come membro della classe, verrà comunque istanziato per istanza di MyClass
, e inoltre, dovrà essere istanziato separatamente per qualsiasi altra classe che lo utilizza. Pertanto, se sei preoccupato per il sovraccarico dovuto alla costruzione di un GeometrySplitter
, spostarlo fuori dall'ambito locale non risolve completamente il problema.
Usa IoC per aggirare tutto questo
In IoC , la creazione dell'oggetto è considerata una preoccupazione separata e fare in modo che MyClass
si preoccupi di come istanziare qualcosa è una violazione di SRP . Questi problemi non dovrebbero essere risolti da MyClass
.
Se utilizzi un contenitore IoC, elimina il problema e potresti anche risparmiare un sovraccarico di istanziazione non solo tra chiamate diverse a MyClass::methodY
ma anche tra chiamate diverse a qualsiasi metodo nella classe qualsiasi che usa lo splitter.
Ad esempio:
public MyClass {
protected readonly IUnityContainer _container;
public MyClass(IUnityContainer container) {
_container = container;
}
public void methodY(int i, object o) {
IGeometrySplitter splitter = _container.Resolve<IGeometrySplitter>();
splitter.chop();
}
}
Le regole di istanza appartengono alla root di composizione
Se vuoi ogni volta una nuova istanza, imposta composizione root in questo modo:
container.RegisterType<IGeometrySplitter, GeometrySplitter>();
Se si desidera riutilizzare una singola istanza (non protetta da thread):
container.RegisterType<IGeometrySplitter, GeometrySplitter>(new PerThreadLifetimeManager());
Se vuoi una singola istanza (thread-safe) che viene riutilizzata:
container.RegisterType<IGeometrySplitter, GeometrySplitter>(new ContainerControlledLifetimeManager());
Quindi, registra MyClass
nel contenitore, in modo che si inietti nel processo di creazione dell'istanza:
container.RegisterType<IUnityContainer>(container);
container.RegisterType<MyClass>();
Quando lo fai in questo modo, Unity si autoiniezione automaticamente come argomento del costruttore su MyClass
in modo che methodY
possa chiamarlo.
Per istanziare MyClass
, usa:
var myClass = container.Resolve<MyClass>();
Note
-
Il mio esempio sopra utilizza Unity , che è la tecnologia ac #. In Java credo che usereste Spring invece (non piuttosto sicuro). Ma il principio è indipendente dal linguaggio e le tecniche per controllare la durata degli oggetti dovrebbero essere simili.
-
Sebbene questo modello non sia troppo raro, alcuni direbbero che è un anti -pattern. Dicevano che dovresti iniettare uno specifico GeometrySplitterFactory
invece del contenitore IoC stesso e implementare le regole di istanza in fabbrica. Ma il principio è lo stesso: prendi le regole di istanziazione da MyClass
.