The following code works very well when all involved classes are in the same project (determineSubClass
is a member of BaseClass
):
protected static BaseClass determineSubClass(String p1, int p2, Boolean p3) {
BaseClass baseObj = null;
if ( (baseObj = SubClassOne.ofType(p1, p2, p3)) != null )
return baseObj;
else if ( (baseObj = SubClassTwo.ofType(p1, p2, p3)) != null )
return baseObj;
else if ( (baseObj = SubClassThree.ofType(p1, p2, p3)) != null )
return baseObj;
else if ( (baseObj = SubClassFour.ofType(p1, p2, p3)) != null )
return baseObj;
else
return new SubClassDefault(p1, p2, p3);
}
But now, I want to move the BaseClass
to a shared Library project, in which SubClassOne
, SubClassTwo
, SubClassThree
and SubClassFour
are not defined in the library but rather in the applications using this library.
I could of course move BaseClass
back to each and every application using this library, but I wonder:
BaseClass
in the Library
project and eliminate the need for it
to know about all superclasses
derived from it?EDIT (answering @ahmet alp balkan question below):
ofType()
of each subclass does 2 things:
As for your second question, BaseClass
at this point holds common data members and methods to all subclasses and only this single static method which is aimed at delegating the responsibility of determining subclass to be instantiated.
BTW, thanks to your question I noticed a horrible typo in my original post: "SuperClassOne" should be "SubClassOne" etc.
Your static determineSubClass
method is a factory method. It should not be located on the BaseClass
; the base class should not know anything about the subclasses. In your case it can't know anything about it, because you want to locate the base class in another project.
Neither should this method be located in a factory class that is responsible for creating BaseClass
instances. What you should do is define an interface for creating BaseClass
instances next to the BaseType
and defines an implementation inside the Composition Root of your application. When you have multiple applications, they probably each have a different set of BaseClass
sub types, so each application will have a different factory. When you have this construction in place, you can inject the factory into classes that need BaseClass
instances.
It might look something like this:
// Shared library
public interface IBaseClassFactory
{
BaseClass CreateNew(String p1, int p2, Boolean p3);
}
public abstract class BaseClass { }
// Application code
public class SubClassOne : BaseClass { }
public class SubClassTwo : BaseClass { }
// Note that this consumer depends on IBaseClassFactory.
public class SomeConsumer
{
private IBaseClassFactory baseClassFactory;
public SomeConsumer(IBaseClassFactory factory)
{
this.baseClassFactory = factory;
}
public void Consume()
{
BaseClass instance = this.baseClassFactory.CreateNew("foo", 0, false);
// use instance
}
}
// Composition Root
class BaseClassFactory : IBaseClassFactory
{
public BaseClass CreateNew(String p1, int p2, Boolean p3)
{
BaseClass baseObj = null;
if ((baseObj = SubClassOne.ofType(p1, p2, p3)) != null)
return baseObj;
// etc
else
return new SubClassDefault(p1, p2, p3);
}
}