ClientInterfaceクラスがあります。このクラスは、Strategyパターンを使用して、インターフェイスAbaseとBbaseにそれぞれ準拠する2つの複雑なアルゴリズムを編成します。ClientInterfaceは、アルゴリズムが動作するデータを(合成を介して)集約します。データは、データインターフェイスに準拠する必要があります。
私がやろうとしたのは、実行時にさまざまな戦略とデータの実装を選択できる単一のClientInterfaceクラスを用意することです。アルゴリズムとデータの実装は、入力ファイルから文字列を読み取り、ClientInterfaceコンストラクターでアルゴリズムとデータの実装を選択するファクトリメソッドを使用して選択されます。データとアルゴリズムの実行時の選択は、以下のコードモデルでは提供されていません。
データの実装は、マップ、リスト、unordered_mapなどに基づいて、2つの複雑なアルゴリズム(AbaseおよびBbaseで実装された戦略)の効率が、データに使用される異なるコンテナーでどのように変化するかをテストできます。
さらに、データはさまざまな要素(ElementBase実装)を集約します。さまざまな要素の実装もClientInterfaceの効率に大きな影響を与えますが、要素は実際にはさまざまなライブラリからの実装とは互いに素なタイプです。既存のアプリケーションをプロファイリングすると、Element操作がボトルネックの1つであることが示されるため、これは事実としてわかっています。
コンテナでポリモーフィズムを使用する場合、そこには「boost / ptr_container」がありますが、データには数百万ではないにしても数十万の要素が格納されます。この場合、要素にポリモーフィズムを使用すると、ClientInterfaceにかなりのオーバーヘッドが発生しますが、データをElementタイプのクラステンプレートにすることを選択すると、ClientInterfaceクラスを静的に定義することになります。つまり、各要素ごとにクライアントアプリケーションを生成します。少なくとも入力してください。
実行時に取得された同じ数の要素とClientInterface構成に対して、要素タイプのポリモーフィズムの使用によって引き起こされるオーバーヘッドが、データとアルゴリズムの実装のすべての構成に同じ影響を与えると想定できますか?この場合、自動テストを実行し、データ実装と要素実装の構成を決定し、生産的なコードで使用される静的に構成されたEfficientClientInterfaceを定義できますか?
目標:テストハーネスを準備しました。実行時にアルゴリズムと要素を変更すると、ループ内で単一のアプリケーションを使用できるため、テストケースファミリーのテストを自動化しようとしています。これは実行時に構成され、その出力は効率のために測定されます。実際の実装では、少なくとも6つのアルゴリズムインターフェイス、3〜4のデータ実装を扱っており、少なくとも3つの要素の実装を見積もっています。
だから、私の質問は次のとおりです。
1)戻り型に対してオーバーロードが機能していない場合、Elementはどのようにさまざまな操作をサポートできますか?操作をテンプレートにする場合は、コンパイル時に定義する必要があります。これは、自動テスト手順を台無しにします。
2)目標を達成するために、このコードをより適切に設計するにはどうすればよいですか?
3)この問題に対するより良い全体的なアプローチはありますか?
コードモデルは次のとおりです。
#include <iostream>
#include <memory>
class ElementOpResultFirst
{};
class ElementOpResultSecond
{};
class ElementBase
{
public:
// Overloading does not allow different representation of the solution for the element operation.
virtual ElementOpResultFirst elementOperation() = 0;
//virtual ElementOpResultSecond elementOperation() = 0;
};
class InterestingElement
:
public ElementBase
{
public:
ElementOpResultFirst elementOperation()
{
// Implementation dependant operation code.
return ElementOpResultFirst();
}
//ElementOpResultSecond elementOperation()
//{
//// Implementation dependant operation code.
//return ElementOpResultSecond();
//}
};
class EfficientElement
:
public ElementBase
{
public:
ElementOpResultFirst elementOperation()
{
// Implementation dependant operation code.
return ElementOpResultFirst();
}
//ElementOpResultSecond elementOperation()
//{
//// Implementation dependant operation code.
//return ElementOpResultSecond();
//}
};
class Data
{
public:
virtual void insertElement(const ElementBase&) = 0;
virtual const ElementBase& getElement(int key) = 0;
};
class DataConcreteMap
:
public Data
{
// Map implementation
public:
void insertElement(const ElementBase&)
{
// Insert element into the Map implementation.
}
const ElementBase& getElement(int key)
{
// Get element from the Map implementation.
}
};
class DataConcreteVector
:
public Data
{
// Vector implementation
public:
void insertElement(const ElementBase&)
{
// Insert element into the vector implementation.
}
const ElementBase& getElement(int key)
{
// Get element from the Vector implementation
}
};
class Abase
{
public:
virtual void aFunction() = 0;
};
class Aconcrete
:
public Abase
{
public:
virtual void aFunction()
{
std::cout << "Aconcrete::function() " << std::endl;
}
};
class Bbase
{
public:
virtual void bFunction(Data& data) = 0;
};
class Bconcrete
:
public Bbase
{
public:
virtual void bFunction(Data& data)
{
data.getElement(0);
std::cout << "Bconcrete::function() " << std::endl;
}
};
// Add a static abstract factory for algorithm and data generation.
class ClientInterface
{
std::unique_ptr<Data> data_;
std::unique_ptr<Abase> algorithmA_;
std::unique_ptr<Bbase> algorithmB_;
public:
ClientInterface()
:
// A Factory Method is defined for Data, Abase and Bbase that
// produces the concrete type based on an entry in a text-file.
data_ (std::unique_ptr<Data> (new DataConcreteMap())),
algorithmA_(std::unique_ptr<Abase> (new Aconcrete())),
algorithmB_(std::unique_ptr<Bbase> (new Bconcrete()))
{}
void aFunction()
{
return algorithmA_->aFunction();
}
void bFunction()
{
return algorithmB_->bFunction(*data_);
}
};
// Single client code: both for testing and final version.
int main()
{
ClientInterface cli;
cli.aFunction();
cli.bFunction();
return 0;
};