2

2 種類のクラス インスタンスをキューに入れたいと考えています。たとえば、次のように、

エンキューするクラス)

class A{
    int a1;
    int a2;
}
class B{
    string b1;
    string b2;
}

サンプル1)

ConcurrentQueue<Object> queue = ConcurrentQueue<Object>();
queue.Enqueue(new A());
queue.Enqueue(new B());
Object item;
while (queue.TryDequeue(out item))
{
    A a = item as A;
    B b = item as B;
    if(a != null){
    }
    else if(b != null){
    }
}

サンプル2)

class AorB{
    public A a = null;
    public B b = null;
    public AorB(A a){ this.a = a; }
    public AorB(B b){ this.b = b; }
}
ConcurrentQueue<AorB> queue = new ConcurrentQueue<AorB>();
queue.Enqueue(new AorB(new A()));
queue.Enqueue(new AorB(new B()));
AorB item;
while (queue.TryDequeue(out item))
{
    if(item.a != null){
    }
    else if(item.b != null){
    }
}

Sample1、Sample2、またはその他の方法では、どちらがより良い方法ですか?

4

4 に答える 4

4

どちらも実際には良い実装ではありません。(コメントで述べたように)それらが印刷やビープ音などのコマンド用であり、それらのメンバーが異なる場合、それらが何をしているのかを考えるべきです。これを回避するより良い方法は、彼らが行っていることを次のようなインターフェースに抽出することです。

public interface ICommand
{
    void Execute();
}

次に、A と B に ICommand を実装させて、印刷とビープ音が A と B によって処理されるようにします。こうすると、呼び出しコードは次のようになります。

ConcurrentQueue<ICommand> queue = ConcurrentQueue<ICommand>();
queue.Enqueue(new A());
queue.Enqueue(new B());
Object item;
while (queue.TryDequeue(out item))
{
    item.execute();
}

これは、「Tell, don't ask」にも当てはまります。

于 2013-07-02T09:27:33.627 に答える
2

これは、Command パターンを適用するのに最適な状況です。

メソッドを公開する共通のインターフェイスを各オブジェクトに実装させますExecute。次に、オブジェクトに、必要な手段でコマンドを実行させます。コマンドの実行をオブジェクト自体にカプセル化することで、コードがよりクリーンで拡張しやすくなります。

これはメモ帳コードであるため、構文に軽微な誤りがある可能性があります。

namespace
{
    public interface ICommand
    {
        public void Execute();
    }

    public class CommandA : ICommand
    {
        public int value;

        public void Execute()
        {
            // Do something here
        }
    }

    public class CommandB : ICommand
    {
        public string value;

        public void Execute()
        {
            // Do something here
        }
    }

    public class Program
    {
        private Queue<ICommand> commands = new Queue<ICommand>();

        public Program()
        {
            this.commands.Enqueue(new CommandA());
            this.commands.Enqueue(new CommandB());

            // Much later
            while (item = this.commands.Dequeue())
            {
                item.Execute();
            }
        }
    }
}
于 2013-07-02T09:30:28.727 に答える
0

まあ、どちらも。たとえば、別のクラスのインスタンスをキューに入れる必要がある場合Cifステートメントは保守可能になります。

デキューされたアイテムをどうするかを考える必要があります。キューに格納するだけの場合は、タイプごとに 2 つ以上のキューを使用します。型に関係なく何かに使用する場合は、型が実装するインターフェイス、または他の型が継承される基本クラスを使用することを検討してください。

このユースケースを提供していないため、私のアドバイスは抽象的なものです。

于 2013-07-02T09:10:36.413 に答える
0

私は実際には1でも2でもないと言います。

A と B が共通のインターフェイスを共有している場合は、どちらの継承も使用しないでください。それ以外の場合は、オブジェクトの種類ごとに 1 つずつ、2 つのキューだけを使用します。

そして、それらに共通するものがない場合は、両方を使用するための単一のコードを作成するべきではありません。ユースケースによっては、タイプごとに 1 つずつ、2 つのスレッドが適切に見える場合があります。

于 2013-07-02T09:10:45.287 に答える