如何逆转班级工厂搬迁到图书馆的依赖性

时间:2011-06-29 20:25:34

标签: java dependency-injection dependency-management library-project class-factory

当所有涉及的类都在同一个项目中时,以下代码非常有效(determineSubClassBaseClass的成员):

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);
}

但是现在,我想将BaseClass移动到共享的库项目,其中SubClassOneSubClassTwoSubClassThreeSubClassFour 在库中定义,而是在使用此库的应用程序中定义。

我当然可以将BaseClass移回使用此库的每个应用程序,但我想知道:

  • 有更好的解决方案吗?
  • 是否有解决方案可以让我 将BaseClass保留在库中 项目并消除它的需要 了解所有超类 从中衍生出来了吗?

编辑(回答@ahmet alp巴尔干问题):

每个子类的

ofType()做两件事:

  1. 根据内容确定 字符串p1和其他参数 p2和p3,是否为子类 被实例化的是类型。
  2. 如果答案是肯定的,那就是 实例化一个自我的对象 子类。否则,返回null。
  3. 关于你的第二个问题,此时BaseClass包含所有子类的公共数据成员和方法,并且只有这个单一的静态方法,旨在委派确定子类的责任进行实例化。

    顺便说一下,多亏了你的问题,我发现原帖中有一个可怕的拼写错误:“SuperClassOne”应该是“SubClassOne”等。

2 个答案:

答案 0 :(得分:1)

基类知道它的超类不是一个好习惯。它违反了大约一半的OO原则;).....

我将这个方法转移到一个名为HierarchyManager的新类,或者像这样的方法,并在那里使用方法。你甚至可以在那里建立一些层次结构 - >你可以有效地使这种方法“可扩展”....

例如,您可以在库中使用:

BaseClass - > A,B(A,B子类化BaseClass) 和一些LibraryHierachyManager处理这三个类...

然后在使用它的应用程序中:

C,D(继承BaseClass或A或B)

和一些ApplicationHieararchyManager在做:

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


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

答案 1 :(得分:1)

您的静态determineSubClass方法是工厂方法。它显然不应该位于BaseClass上,因为不仅基类不应该知道关于子类的任何内容,但是在你的情况下它不能知道任何关于它的东西,因为你想要找到基类另一个项目。不,此方法应位于负责创建BaseClass实例的工厂类中。您应该做的是定义用于在BaseClass旁边创建BaseType实例的接口(或基本类型),并在应用程序的composition root中定义实现。当您有多个应用程序时,它们可能各自具有不同的BaseClass子类型集,因此每个应用程序将具有不同的工厂。当您具有此构造时,可以将工厂注入需要BaseClass个实例的类。

它可能看起来像这样:

// 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);
    }
}