开发者

How to Reverse Dependency for Class Factory moved to a Library

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:

  • Is there a better solution?
  • Is there a solution that would let me keep 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:

  1. Determines, based on the content of String p1 and the other parameters p2 and p3, whether the subclass to be inst开发者_如何学Pythonantiated is of its type.
  2. If the answer is positive, it instantiates an object of self subclass. Otherwise, returns null.

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 obviously not be located on the BaseClass, since not only the base class should not know anything about the subclasses, but in your case it can't know anything about it, since you want to locate the base class in another project. No, this method should be located in a factory class that is responsible for creating BaseClass instances. What you should do is define an interface (or base type) for creating BaseClass instances next to the BaseType and defines an implementation in 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);
    }
}


It's not a good practice that the base class knows about its super classes. It violates about half of OO principles ;).....

I'd move out the method to a new Class called HierarchyManager or smth like that and have the method there. You could even build some hierarchy there -> you could effectively make this method "extendable" ....

For example in library you could have:

BaseClass -> A, B (A, B subclassing BaseClass) and some LibraryHierachyManager handling these three classes...

and then in application using it:

C, D (subclassing BaseClass or A or B)

and some ApplicationHieararchyManager doing:

public static BaseClass determineSubClass(String p1, int p2, Boolean p3) {
    if (baseObj = C.ofType(.....) { 
    ....


    } else {
      return LibraryHierarchyManager.determineSubClass(p1,p2, p3);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜