2

次のコードは、関連するすべてのクラスが同じプロジェクトにある(determineSubClassのメンバーである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);
}

BaseClassしかし今、私は共有ライブラリプロジェクトに移動したいと思います。このプロジェクトではSubClassOne、、、がライブラリSubClassTwoではなく、このライブラリを使用するアプリケーションで定義されています。SubClassThreeSubClassFour

もちろんBaseClass、このライブラリを使用してすべてのアプリケーションに戻ることもできますが、疑問に思います。

  • より良い解決策はありますか?
  • ライブラリプロジェクトを維持BaseClassし、ライブラリプロジェクトから派生したすべてのスーパークラスについて知る必要をなくすソリューションはありますか?

編集(以下の@ahmet alp balkanの質問に答える):

ofType()各サブクラスの2つのことを行います:

  1. 文字列p1と他のパラメータp2およびp3の内容に基づいて、インスタンス化されるサブクラスがそのタイプであるかどうかを判別します。
  2. 答えが肯定的である場合、それは自己サブクラスのオブジェクトをインスタンス化します。それ以外の場合は、nullを返します。

2番目の質問についてはBaseClass、この時点で、すべてのサブクラスに共通のデータメンバーとメソッドがあり、インスタンス化するサブクラスを決定する責任を委任することを目的としたこの単一の静的メソッドのみが保持されます。

ところで、あなたの質問のおかげで、私は私の元の投稿でひどいタイプミスに気づきました:「SuperClassOne」は「SubClassOne」などでなければなりません。

4

2 に答える 2

1

静的determineSubClassメソッドはファクトリメソッドです。BaseClass基本クラスはサブクラスについて何も知らないだけでなく、別のプロジェクトで基本クラスを見つけたいので、あなたの場合はそれについて何も知ることができないので、それは明らかにに配置されるべきではありません。BaseClassいいえ、このメソッドは、インスタンスの作成を担当するファクトリクラスに配置する必要があります。行うべきことは、のBaseClass隣にインスタンスを作成するためのインターフェース(または基本タイプ)を定義し、アプリケーションのコンポジションルートBaseTypeに実装を定義することです。複数のアプリケーションがある場合、それらはおそらくそれぞれ異なるセットを持っています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);
    }
}
于 2011-06-30T04:30:54.733 に答える
1

基本クラスがそのスーパークラスについて知っているのは良い習慣ではありません。OOの原則の約半分に違反しています;)....。

メソッドをHierarchyManagerまたはそのようなsmthという新しいクラスに移動し、そこにメソッドを配置します。そこに階層を構築することもできます->このメソッドを効果的に「拡張可能」にすることができます...。

たとえば、ライブラリでは次のことができます。

BaseClass-> A、B(A、BはBaseClassをサブクラス化)およびこれらの3つのクラスを処理するいくつかの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);
    }
}
于 2011-06-30T00:47:34.227 に答える