データに関する設計上の質問があります。以下に説明するように、2つのデータ型を処理する単一のインターフェースを持つクラス「T」があります。クラスTは、2つのデータ型のいずれかを処理するように構築されています。 Tクラスのユーザーは、Tクラスが処理するデータのタイプを知る必要はありません。
「UL」オブジェクトを関数の引数として渡さないようにする方法があるかどうかも疑問に思っていました。たとえば、クラスTの外部に参照を設定でき、ULオブジェクトが変更されるたびに、新しいULが参照に割り当てられます。これにより、ULのさまざまなインスタンスを固定参照の背後に隠すことができますか?次に、データ型Lのシングルトンと同様に、クラスTの固定参照に何らかの方法でアクセスできますか?
私はこのデザインに行き詰まり、何か大きなものを見逃したのではないかと思います。
class P
{
Ts ts_;
public void work(UL_Data ul_data)
{
ts_.work(ul_data)
}
}
class Ts
{
IList<T> ts_;
public void work(UL_Data ul_data)
{
//...
foreach(var t in ts_)
{
double val = t.read(ul_data);
//....
}
//...
}
}
class T
{
//set to true if the class read data type L
bool data_type_L;
public double read(UL_Data ul_data)
{
if(!data_type_L)
//...read data type L from singleton
else
//read data type UL from function argument ul_data
}
}
質問を正しく理解すると、作業を実行する2種類のオブジェクトを含める必要があるリストがあります。ただし、これら2つのタイプのメソッドは引数が異なります。 1つは単一の入力(ul_data
)もう一方は何も入力せずに作業を実行できます(つまり、他の場所からデータを取得するためです)。
言い換えると、共通のインターフェースに対する欲求は共通のメソッド(存在しない)ではなく、両方のクラスをList<T>
。
これを行う最も基本的な方法は、マーカーリストを使用して(リストに含めるため)、メソッドをオフのままにすることです。呼び出し元のコードは、リストをフィルタリングし、そのタイプに適した方法で各項目を呼び出す必要があります。
interface IMarkerInterface
{
//Empty
}
class TUL : IMarkerInterface
{
public void Read(ULData ulData)
{
//Do something with the data
}
}
class TL : IMarkerInterface
{
public void Read()
{
//Get the data from somewhere else, and do something with it
}
}
次に、オブジェクトを同じリストに入れることができます。
var list = new List<IMarkerInterface>
{
new TUL(),
new TL()
};
リストを反復処理して引数を渡すには、残念ながら呼び出し側が型を知っている必要があります。これがコードが引数を渡す唯一の方法ですが、常にではありません。
したがって、リストを反復処理するには、次のようなリストを作成します。
foreach (var tl in list.OfType<TL>())
{
tl.Read();
}
foreach (var tul in list.OfType<TUL>())
{
tul.Read(argument);
}
つまり、これは最後の手段のようなものです。おそらく、オブジェクトモデルをリファクタリングする方法があるため、個々のオブジェクトのタイプを調べてそれを呼び出す方法を知る必要はありません。たとえば、インスタンスの作成時にul_dataを渡すことができた場合などです。しかし、これにどう対処するかをアドバイスするには、これらのクラスの真の関係、つまりそれらの目的についてもっと知る必要があります。 T
、UL
、およびL
という名前だけでは、言うことはできません。
ちょっと掛け算の方法を考えてみましょう:
_x.multiply(y);
_
このメソッドは_x * y
_を返します。xは、現在保持しているintで構築されたオブジェクトです。つまり、これは成功します:
_assert(new X(2).multiply(2) == 4);
_
これまでのところこれはすべて妥当なように見えますが、次のようになるとどうなりますか。
_assert(new X(0).multiply(2) == 0);
_
これには、実装にifを含める必要がありますか?本当に2に依存していないように見えるのは悪い習慣ですか?
いいえ。ifなしでこれを行うことは絶対に問題ありません。インターフェースが特定の状態を前提として、実際には必要としないものを要求することは、まったく問題ありません。
したがって、私はあなたのインターフェースが次のようであることで全く問題ありません:
_t.read(ul_data);
_
tの状態や含まれるブール値に関係なく。結び目であなたを結びつけているのは、何にも関係がないことです。奇妙な考えは何もありません。時々、何かを得てそれで何もしないのは非常に奇妙に思えます。しかし、多くの場合、それはまさにあなたがすべきことです。
パラメータを使用してニーズを表明しますが、毎回使用することが保証されているとは考えないでください。時にはそうでないこともあります。
ここで問題を引き起こす可能性があるのは、t
が_ul_data
_を必要としないことを静的に知っているときにこのインターフェイスを回避する方法がない場合です。 _ul_data
_を渡さずにシングルトンデータ読み取りコードにアクセスする方法がいくつかあるはずです。しかし、それはこのコードがそれを使用する必要があるという意味ではありません。このコードは知らないt
の状態を試みています。それはむしろわからないです。 x.multiply(2)
を呼び出すときと同じですわからない現在のxは何ですか。
しかし、t
が本当に何であるかをすでに知っている場合は、_ul_data
_を扱わないようにする方法が必要です。
どうして?同じ理由で、2またはyを渡す必要はありません。
_assert(new X(0).getX() == 0);
_