0

私は OO パターンの方法で学ぶべきことがたくさんあります。これは私が何年にもわたって遭遇してきた問題です。クラスの唯一の目的が手続き型であり、基本的に手続きをクラスにまとめるだけの状況に陥ります。オブジェクト指向の正しいやり方とは思えません。この問題を別の方法で検討するのに十分な経験がある人がいるのだろうかと思います。現在のアプリケーションでの私の具体的な例は次のとおりです。

私のアプリケーションでは、エンジニアリング調査機器から一連のポイントを取得し、それらを正規化してプログラムの他の場所で使用しています。「正規化」とは、目的の方向に到達するまでの完全なデータ セットの一連の変換を意味します。

各変換プロシージャは、点の配列 (つまり、形式class point { float x; float y; float z; }) の入力を受け取り、同じ長さの配列を返しますが、値は異なります。たとえば、 のような変換point[] RotateXY(point[] inList, float angle)。もう 1 つの種類の手順は、正規化プロセスを補足し、次に行う変換を決定するために使用される分析タイプです。このタイプのプロシージャは、同じポイントをパラメーターとして受け取りますが、異なる種類のデータセットを返します。

私の質問は、この状況で使用するのに適したパターンは何ですか? 私がコーディングしようとしていたのは、たとえば RotationXY のクラス タイプを継承する正規化クラスでした。しかし、RotationXY の唯一の目的はポイントを回転させることなので、基本的には単一の関数を実装することになります。ただし、最初の段落で述べた理由から、これはあまり良いとは言えません。

前もって感謝します!

4

4 に答える 4

3

問題のドメインで候補クラスを見つけるための最も一般的/自然なアプローチは、名詞を探し、それらの名詞に関連付けられた動詞/アクションをスキャンして、各クラスが実装する必要がある動作を見つけることです。これは一般的に良いアドバイスですが、オブジェクトが具体的な要素のみを表す必要があるという意味ではありません。プロセス (通常はメソッドとしてモデル化される) が成長し始めて複雑になった場合、それらをオブジェクトとしてモデル化することをお勧めします。したがって、変換自体に重みがある場合は、それをオブジェクトとしてモデル化し、次のようにしても問題ありません。

class RotateXY
{
public function apply(point p)
{
//Apply the transformation
}
}

t = new RotateXY();
newPoint = t->apply(oldPoint);

多くの変換がある場合は、ポリモーフィック階層を作成し、1 つの変換を別の変換にチェーンすることさえできます。もう少し深く掘り下げたい場合は、これに密接に関連するCommandデザイン パターンも参照してください。

いくつかの最終的なコメント:

  • 自分のケースに当てはまる場合は、ポイント レベルで変換をモデル化し、それをポイントのコレクションに適用することをお勧めします。そうすることで、変換の概念を適切に分離でき、テスト ケースの作成も容易になります。必要に応じて、後で変換のコンポジットを作成することもできます。
  • Utilsほとんどの場合、モデルにその動作を実行する抽象化が欠けていることを意味するため、静的メソッドの束を持つ(または類似の)クラスは一般的に好きではありません。

HTH

于 2012-11-20T12:00:01.093 に答える
1

通常、静的メソッドのみを含むクラスに関しては、それらを Util と名付けます。たとえば、ファサード DB アクセスの場合は DbUtil、ファイル I/O の場合は FileUtil などです。おそらくあなたの場合、 GeometryUtil またはそれらの線に沿ったものです。

于 2012-11-19T23:46:32.877 に答える
1

適用する変換の詳細は、問題に対してアドホックであり、将来変更される可能性があるため、構成ファイルでそれらをコーディングできます。

ポイントのクライアントはファイルから読み取り、何をすべきかを知っています。回転やその他の変換方法については、Point クラスの一部としてうまくいく可能性があります。

于 2012-11-19T23:51:13.150 に答える
1

クラス/インターフェースが本質的に1つのメンバーしか持たないことに特に問題はないと思います。

あなたの場合、メンバーは「同じ型を返す1つの型のいくつかの引数を持つ操作」です-いくつかの数学/機能上の問題に共通です。複数の変換クラスを組み合わせてより複雑な変換を行うインターフェイス/基本クラスとヘルパー メソッドがあると便利な場合があります。

代替アプローチ: 言語をサポートする場合は、完全に機能的なスタイルになります (C# の LINQ に似ています)。

機能的なスタイルの提案について: 次の基本的な関数から始めます (おそらく、言語の標準ライブラリでそれらを見つけるだけです)。

  • collection = map(collection, perItemFunction)コレクション内のすべてのアイテムを変換する ( SelectC#)
  • item = reduce (collection, agregateFunction)すべてのアイテムを単一のエンティティに削減する ( AggregateC# の場合)
  • アイテムの 2 つの機能を組み合わせますfuncOnItem = combine(funcFirst, funcSecond)。C# ではラムダとして表現できますFunc<T,T> combined = x => second(first(x))
  • "bind"/カリー- 関数の引数の 1 つを修正しますfunctionOfOneArg = curry(funcOfArgs, fixedFirstArg)。C# では lambda として表現できますFunc<T,T> curried = x => funcOfTwoArg(fixedFirstArg, x)

このリストでは、「X 軸上のコレクション内のすべてのポイントを 10 回転させ、Y を 15 だけシフトする」などの操作を実行できますmap(points, combine(curry(rotateX, 10), curry(shiftY(15)))

構文は言語によって異なります。つまり、JavaScript では関数を渡すだけで (map/reduce は既に言語の一部です)、C# - ラムダとFuncクラス (引数 function - のようにFunc<T,R>) はオプションです。一部の言語では、クラス/インターフェイスを明示的に使用して「関数」オブジェクトを表す必要があります。

代替アプローチ: 実際にポイントと変換を扱う場合、別の従来のアプローチは、Matrix を使用してすべての線形操作を表すことです (言語がカスタム演算子をサポートしている場合、非常に自然なコードが得られます)。

于 2012-11-19T23:52:01.333 に答える