Member scope doesn't solve the problem fully
Even if you declare GeometrySplitter
as a class member, it will still get instantiated per instance of MyClass
, and in addition, will need to be instantiated separately for any other class that uses it. So if you're worried about the overhead of constructing a GeometrySplitter
, moving it out of local scope doesn't fully solve the problem.
Use IoC to get around all this
Under IoC, object creation is considered a separate concern, and making MyClass
worry about how to instantiate something is a violation of SRP. These problems shouldn't need to be solved by MyClass
.
If you use an IoC container, it eliminates the problem, and also might save you some instantiation overhead not just between different calls to MyClass::methodY
but also between different calls to any method in any class that uses the splitter.
For example:
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();
}
}
Instancing rules belong in the composition root
If you want a new instance each time, set up your composition root this way:
container.RegisterType<IGeometrySplitter, GeometrySplitter>();
If you want one single (non-thread-safe) instance that is re-used:
container.RegisterType<IGeometrySplitter, GeometrySplitter>(new PerThreadLifetimeManager());
If you want one single (thread-safe) instance that is re-used:
container.RegisterType<IGeometrySplitter, GeometrySplitter>(new ContainerControlledLifetimeManager());
Then, register MyClass
in the container as well, so that it will inject itself into the instantiation process:
container.RegisterType<IUnityContainer>(container);
container.RegisterType<MyClass>();
When you do it like this, Unity will automatically inject itself as the constructor argument to MyClass
so that methodY
can call it.
To instantiate MyClass
, use:
var myClass = container.Resolve<MyClass>();
Notes
My example above uses Unity, which is a c# technology. In Java I believe you'd use Spring instead (not quite sure). But the principle is language-agnostic and the techniques to control object lifespan should be similar.
While this pattern isn't too uncommon, some folks would say that it's an anti-pattern. They'd say you'd have to inject a specific GeometrySplitterFactory
instead of the IoC container itself, and implement instantiation rules in the factory. But the principle is the same: take the instantiation rules out of MyClass
.
splitter
can be accessed from different threads, which might interfere with thechop
method.