5

アプリケーションアーキテクチャの障害になりました。ビジターパターンを使用して、実行時にわからないタイプの抽象オブジェクトに対して特定のアルゴリズムを実行し始めました。私の問題は、私のアルゴリズムがネストされた抽象型の型にも依存していることです。

私が何を意味するかを説明しましょう:

抽象DataSourceクラスがあります。これから、concereteDataSourceReferenceクラスとDataSourceExplicitクラスを実装します。また、抽象Reportクラス(逆シリアル化されたメタデータ)があり、そこから具体的なReportクラスReportTypeAおよびReportTypeBを実装します。これらのオブジェクトが作成されるとき、それらのDataSourceは任意の拡張DataSourceクラスである可能性があります。

それに応じて実行できるように、実際のレポートタイプとデータソースタイプの両方が必要です。ビジターパターンを使用してコンサートレポートタイプを取得できますが、後でDataSourceに対して同じことを行う方法がわかりません。

レポートにアクセスした後、データソースにアクセスできません。具体的なタイプのレポートを失うためです(基本のレポートタイプを受け入れる必要があるため:Accept(SomeDataSourceVisitor d、MetaReport m)-またはすべての可能なレポートタイプに対してオーバーロードします、これはビジターパターンの目的を無効にします。私の問題を参照してください。

何か案は?ディスパッチャ(訪問者)が新しいレポートをサポートしていることを確認するために新しいレポートタイプの開発者を必要としないため、動的な使用は避けたいと思います。

現在のコード:

public abstract class DataSource
{
}

public class DataSourceReference : DataSource
{
    // reference thing(s)
}

public class DataSourceExplicit : DataSource
{
    // explicit thing(s)
}

public abstract class Report
{
    // some shared Report attribute(s)
    // ...

    public DataSource DataSource { get; set; }

    public abstract FinalReport Execute(IReportExecutionDispatcher d);
}

public class ReportA : Report
{
    // ReportA specific attribute(s)
    // ...

    public override Execute(IReportExecutionDispatcher d)
    {
        d.ExecuteReport(this);
    }
}

public class ReportB : Report
{
    // ReportB specific attribute(s)
    // ...

    public override Execute(IReportExecutionDispatcher d)
    {
        d.ExecuteReport(this);
    }
}

public interface IReportExecutionDispatcher
{
    FinalReport ExecuteReport(ReportA);
    FinalReport ExecuteReport(ReportB);
}
4

2 に答える 2

3

また、インターウェブを精査しているときにこれを見つけました。今後の参照と議論のためにここに投稿してください。

選択的ビジターパターン

選択的ビジターパターンを使用する場合

  • 複数の分類(理想的にはメソッドのオーバーロード)をサポートするプログラミング言語を使用しています。
  • オブジェクト構造内の(潜在的に異なる種類の)要素に対してさまざまな種類の操作を実行する必要があります。
  • 本質的な責任に関係のない操作で要素クラスを汚染することを避けたいと思います。
  • 既存の設計を損なうことなく、新しい種類の要素を構造に簡単に追加できるようにする必要があります。
于 2012-02-19T17:56:44.943 に答える
2

N * Mメソッドが必要です。ここで、Nはレポートタイプの数、Mはデータソースタイプの数です。ここでの正しいアプローチは、それらをNタイプに分割し、それぞれにMメソッドと1つのヘルパータイプを追加することです。これは、ディスパッチの最初のステップを作成するのに役立ちます。このようなもの:

public interface IDataSourceExecutionDispatcher
{
    FinalReport ExecuteReport(DataSourceExplicit dataSource);
    FinalReport ExecuteReport(DataSourceReference dataSource);
}

public interface IReportExecutionDispatcher
{
    IDataSourceExecutionDispatcher GetDataSourceDispatcher(ReportA report);
    IDataSourceExecutionDispatcher GetDataSourceDispatcher(ReportB report);
}

public class ReportExecutionDispatcher: IReportExecutionDispatcher
{
    public IDataSourceExecutionDispatcher GetDataSourceDispatcher(
         ReportA report)
    {
        return new ReportADataSourceExecutionDispatcher(report);
    }

    public IDataSourceExecutionDispatcher GetDataSourceDispatcher(
         ReportB report)
    {
        return new ReportBDataSourceExecutionDispatcher(report);
    }
}

class ReportADataSourceExecutionDispatcher : IDataSourceExecutionDispatcher
{
    public ReportADataSourceExecutionDispatcher(ReportA report)
    {
        // save the report into a field
    }

    public FinalReport ExecuteReport(DataSourceExplicit dataSource)
    {
        // use saved report A and explicit dataSource here
    }

    public FinalReport ExecuteReport(DataSourceReference dataSource)
    {
        // similar, but with reference dataSource
    }
}

class ReportBDataSourceExecutionDispatcher : IDataSourceExecutionDispatcher
{
     // similar to ReportA dispatcher, except it takes ReportB in constructor
}

ここで、新しいディスパッチャを受け入れるようにデータソースを変更する必要があります。

public abstract class DataSource
{
    public abstract FinalReport Execute(IDataSourceExecutionDispatcher d);
}

public class DataSourceReference : DataSource
{
    public override FinalReport Execute(IDataSourceExecutionDispatcher d)
    {
        return d.ExecuteReport(this);
    }
}

また、レポートを変更します。

public abstract class Report
{
    public DataSource DataSource { get; set; }

    public abstract FinalReport Execute(IReportExecutionDispatcher d);
}

public class ReportA : Report
{
    public override FinalReport Execute(IReportExecutionDispatcher d)
    {
        var dispatcher = d.GetDataSourceDispatcher(this);
        return DataSource.Execute(dispatcher);
    }
}
于 2012-02-19T12:45:19.427 に答える