3

いくつかのクラスがあり、それぞれが特定のタスクを実行するゲームを作成しています。

私は OOP にまったく慣れていないので、静的クラス、メソッド、およびプロパティを繰り返さずにクラス インスタンスが相互に通信できるようにするにはどうすればよいか考えていましたが、これはひどいことのように思えます。

私は独学のプログラマーであり、多くの悪い習慣を行っていることを認識しています。これまでのところ、両方のクラスを静的にしてこの作業を行うことができましたが、コードをできるだけ良くするために何をすべきかを知りたいと思っていました。

また、このトピック (インスタンス間の通信) についてもっと読むことができるように、いくつかのリソース/書籍/記事をお勧めしていただければ幸いです。

私が話していることを理解できるように、ここにいくつかのコードを示します。

class Program
{
    static void Main(string[] args)
    {
        Class1 instance1 = new Class1();
        Class2 instance2 = new Class2();

        // infinite loop
        while (true)
        {
            instance1.UpdateMethod(someValue);
            instance2.UpdateMethod();
        }
    }
}

class Class1
{
    int Property;
    UpdateMethod(int argument)
    {
        Property += argument;
        if(Property == 3000)
        {
            // I should change the state of instance2
        }
    }
}

class Class2
{
    UpdateMethod()
    {
        if(Time.GetTime() == SomeTime)
        {
            // here I want to change the state of instance1
        }
    }
}
4

5 に答える 5

2

一般的な設計パターンの概要については、

http://en.wikipedia.org/wiki/Category:Software_design_patterns

Class1と の間に自然な関係がある場合Class2、あるインスタンスが別のインスタンスへの参照を保持することは非常に一般的です。たとえば、Playerクラスがあり、プレーヤーに がある場合、次Weaponのようにクラスを定義します。

public class Player
{
    public Weapon Weapon { get; set; }
    // Other properties
}

Class1具体的には、 のインスタンスから のインスタンスを更新したいようですClass2。上記の例のように、Class2関連する のインスタンスを保持するon プロパティを定義することをお勧めします。Class1

これは複合パターンと呼ばれます。

ソフトウェア エンジニアリングでは、複合パターンは分割設計パターンです。複合パターンは、オブジェクトのグループがオブジェクトの単一のインスタンスと同じように扱われることを示しています。コンポジットの目的は、オブジェクトをツリー構造に「構成」して、部分全体の階層を表すことです。複合パターンを実装すると、クライアントは個々のオブジェクトと構成を均一に扱うことができます。

オブジェクト インスタンスに作用するために頻繁に使用される別のパターンは、コマンド パターンです。

オブジェクト指向プログラミングでは、コマンド パターンは、オブジェクトを使用して後でメソッドを呼び出すために必要なすべての情報を表現およびカプセル化する設計パターンです。この情報には、メソッド名、メソッドを所有するオブジェクト、およびメソッド パラメータの値が含まれます。コマンド パターンに常に関連する 3 つの用語は、クライアント、インボーカー、レシーバーです。クライアントはコマンド オブジェクトをインスタンス化し、後でメソッドを呼び出すために必要な情報を提供します。呼び出し元は、メソッドをいつ呼び出すかを決定します。レシーバーは、メソッドのコードを含むクラスのインスタンスです。コマンド オブジェクトを使用すると、委任する必要がある一般的なコンポーネントを簡単に作成できます。

于 2012-07-06T00:17:28.393 に答える
0

オブジェクトの状態を別のクラスから変更する必要がある場合は、そのオブジェクトへの参照が必要です。これを行う一般的な方法は、コンストラクターを使用することです。

public class Class2
{
    private readonly Class1 instance;

    public Class2(Class1 instance)
    {
        this.instance = instance;
    }

    public void UpdateMethod()
    {
        if(VisualStyleElement.TaskbarClock.Time.GetTime() == SomeTime)
        {
            // here I want to change the state of instance1
            this.instance.SomeProperty = "Some Value";
        }
    }
}

またはメソッドに渡されたパラメーターを介して

public class Class2
{
    public void UpdateMethod(Class1 instance)
    {
        if (VisualStyleElement.TaskbarClock.Time.GetTime() == SomeTime)
        {
            // here I want to change the state of instance1
            instance.SomeProperty = "Some Value";
        }
    }
}

最初のケースでは、次のように呼び出します。

Class2 instance2 = new Class2(instance1);
instance2.UpdateMethod();

2 番目のケースでは、次のように呼び出します。

Class2 instance2 = new Class2();
instance2.UpdateMethod(instance1);
于 2012-07-06T00:19:59.533 に答える
0

それはすべて、 と が何Class1Class2あるか、およびそれらを結合する必要があるかどうかによって異なります。それらが無関係なことを行い、お互いについて知る必要がない場合は、イベントを使用してそれらの間で変更を伝達できます。

class Program
{
    static void Main(string[] args)
    {
        Class1 instance1 = new Class1();
        Class2 instance2 = new Class2();

        instance1.CriticalValueReached += instance2.DoSomething;
        instance2.TimeoutElapsed += instance1.DoSomething;

        // infinite loop
        while (true)
        {
            instance1.UpdateMethod(someValue);
            instance2.UpdateMethod();
        }
    }
}

class Class1
{
    int Property;

    public event Action CriticalValueReached;

    public UpdateMethod(int argument)
    {
        Property += argument;
        if (Property == 3000)
            RaiseCriticalValueReached();
    }

    public void DoSomething()
    {
        // Whatever...
    }

    private void RaiseCriticalValueReached()
    {
        var handler = CriticalValueReached;
        if (handler != null)
            handler();
    }
}

class Class2
{
    public event Action TimeoutElapsed;

    public UpdateMethod()
    {
        if (Time.GetTime() == SomeTime)
            RaiseTimeoutElapsed();
    }

    public void DoSomething()
    {
        // ...
    }

    private void RaiseTimeoutElapsed()
    {
        var handler = TimeoutElapsed;
        if (handler != null)
            handler();
    }
}
于 2012-07-06T01:02:27.547 に答える