アルゴリズムをクラスにカプセル化する
-
03-07-2019 - |
質問
アルゴリズムをクラスにカプセル化することはどのように(一般的ではない)疑問に思っていますか?より具体的には、相互に共通のパラメータを転送する多数の個別の関数を使用する代わりに:
void f(int common1, int param1, int *out1);
void g(int common1, int common2, int param1, int *out2)
{
f(common1, param1, ..);
}
共通パラメーターをクラスにカプセル化し、コンストラクターですべての作業を行う:
struct Algo
{
int common1;
int common2;
Algo(int common1, int common2, int param)
{ // do most of the work }
void f(int param1, int *out1);
void g(int param1, int *out2);
};
関数の引数を介して共通のパラメータと中間結果を転送する必要がないのは非常に実用的です。しかし、この「パターン」は見ていません。広く使用されている..マイナス面は何ですか?
解決
これは悪い戦略ではありません。実際、言語(C ++で行う)で、基礎となる機能への不透明なインターフェイスを定義する抽象スーパークラスのタイプを定義できる場合、実行時にさまざまなアルゴリズムを入れ替えることができます(ソートアルゴリズムを考える、例えば)。選択した言語にリフレクションがある場合は、無限に拡張可能なコードを使用することもできます。これにより、アルゴリズムの消費者が作成されたときに存在しなかったアルゴリズムをロードして使用できます。これにより、他の機能クラスとアルゴリズムクラスを大まかに結合することもできます。これは、大規模なプロジェクトで作業する場合のリファクタリングと健全性の維持に役立ちます。
もちろん、複雑なクラス構造の構築を開始するたびに、構築と保守が必要な追加のアーキテクチャ、つまりコードがあります。ただし、私の意見では、長期的なメリットはこの小さな不便を上回っています。
最後の提案:コンストラクターで作業を行わない 。コンストラクタは、クラスの内部構造を適切なデフォルトに初期化するためにのみ使用する必要があります。はい、他のメソッドを呼び出して初期化を完了することもできますが、初期化は not 操作です。探している特定のアルゴリズムを実行するためにコードでもう1つの呼び出しが必要な場合でも、2つは分離する必要があります。
他のヒント
この問題に対処するデザインパターンがあります。 「戦略設計パターン」と呼ばれます。 -こちらでいくつかの良い情報を見つけることができます。
"戦略"の良いところアルゴリズムのファミリーを定義し、アルゴリズムを使用するクライアントを変更することなくそれらを交換可能に使用できるということです。
あなたの質問は、「ソフトウェアの主なアイデアがアルゴリズムを実行しているだけの場合、オブジェクト指向設計をどのように使用しますか?」
その場合、あなたが提供したようなデザインは良い最初のステップだと思いますが、これらは多くの場合問題に依存しています。
良い一般的なデザインは、そこにあるようなものだと思います。 。 。
class InputData {};
class OutputData {};
class TheAlgorithm
{
private:
//functions and common data
public:
TheAlgorithm(InputData);
//other functions
Run();
ReturnOutputData();
};
次に、それをmain()またはGUIとやり取りさせます。
通常、ファンクターまたは関数オブジェクトを作成して、アルゴリズムをカプセル化します。
通常、次のテンプレートを使用します
class MyFunctor {
public:
MyFunctor( /* List of Parameters */ );
bool execute();
private:
/* Local storage for parameters and intermediary data structures */
}
次に、このようにファンクターを使用しました:
bool success = MyFunctor( /*Parameter*/ ).execute();
おそらく、(私が何かを逃していない限り)より良いアプローチは、クラス内のアルゴリズムをecapsualteし、メソッド呼び出しを通じて実行させることです。コンストラクターを介してすべてのパラメーターをパブリックプロパティに渡すか、アルゴリズムを含むクラスに渡されるすべてのパラメーターをカプセル化する構造体を作成できます。しかし、通常、そのようなコンストラクタで物事を実行することは良い考えではありません。何よりもまず、直感的ではないからです。
public class MyFooConfigurator
{
public MyFooConfigurator(string Param1, int, Param2) //Etc...
{
//Set all the internal properties here
//Another option would also be to expose public properties that the user could
//set from outside, or you could create a struct that ecapsulates all the
//parameters.
_Param1 = Param1; //etc...
}
Public ConfigureFoo()
{
If(!FooIsConfigured)
return;
Else
//Process algorithm here.
}
}
コンストラクターパラメーターを使用して両方のメソッドを呼び出す必要がある場合は、それを行います。
同じパラメーターで両方のメソッドを呼び出す必要がない場合は、そうしません。