0

編集:より具体的なコードを提供するために編集しました

ご覧のとおり、私のスプライトの描画はこの規則に違反しています。

誰かが以下の私のコードに基づいて疑似コードを使用して説明できれば、本当に感謝しています(これは、このルールの説明をたくさん読んだためですが、なぜそれが問題なのか、どうすればよいのかまだよくわかりませんこのルールを破らずに行う必要があります :-( )

1)これが私のコードで問題を引き起こすのはなぜですか?

&

2)私がやろうとしていることを行う別の方法を説明してください (リソースをロードしてスプライト オブジェクトを作成するための別のリソース クラスを保持しながら)。


2 つ以上のクラス オブジェクトを介してオブジェクトにアクセスすることに問題はありますか。いくつかのコードで説明します:

ここに 3 つのクラスがあります。以下の 3 番目のクラスのように、別のオブジェクトを介して class2 からメソッドにアクセスすることに何か問題がありますか?.......:

コード

マイ リソース クラス

//Resource class
public Class Resource(){

    Bitmap myTexture;
    Quad mySprite;

public void LoadResources(){

    //Load graphics
    myTexture = BitmapFactory.decodeResource(view.getResources(), R.drawable.myBitmap);

    //Create my objects
    mySprite = new Quad();                //Create new Quad object
    mySprite.setTexture(myTexture);  //Set texture to this quad
    mySprite.setSize(100,100);           //Set size of this quad


    }  

}

私のクワッドクラス

public class Quad(){

//This custom class has the bulk of the code to create all of the Quads / Sprites

public void setTexture(Bitmap textre){
//etc.....
}

//etc....


}

public void draw(int x, int y){

//Draw code here

}

そして最後に、メインの GLRenderer クラス:

public class MyGLRenderer implements GLSurfaceView.Renderer{

    Resource res;

    public MyGLRenderer(){

    res = new Resources();  //Create object to my resources

}

public voide onDrawFrame(){



    //Here is my main loop and I need to draw my sprites here, so........

    res.mySprite.draw(x, y);    //Draw my sprite

}
4

3 に答える 3

7

複数のメソッド呼び出しを連鎖させるのがよくない理由

これが違反する法律

これは、デメテルの法則として知られるコーディング慣行に違反しています。この法律は、「あなたの隣にいる」クラスとのみ話すべきであると述べています。

なぜこれが悪いことなのか

これは、他のいくつかのクラスのメソッドを呼び出すことによって、クラスがそれらのメソッドについて知る必要があり、それらのメソッドの変更に依存するためです。これを密結合と呼びます。メソッドが変更された場合、他のクラスの多くのコードを変更する必要があります。これは「ショットガン サージェリー」と呼ばれ、プログラムの望ましい機能ではありません。

可能な解決策

プロキシの設計パターンを調べます。主に別のクラスへのインターフェイスを提供するように設計されており、ここで役立つ場合があります。おそらく、両方のオブジェクトへの参照を持つことで、このクラスは、すべてのメソッドが通信するための共通のインターフェイスを提供し、クラス間の結合を減らすことができます。

あなたの例を助けるために編集

あなたの例は実際にはそれほど悪くはありません。オブジェクトを取得し、それに対してメソッド呼び出しを行います。依存関係には 1 つの形式がありmySpriteます。クラスからフィールドを削除するとコードが機能しなくなりdraw、スピリットからメソッドを削除するとコードが機能しなくなります。私にとって最も簡単な解決策は、 aを引数として受け入れるというクラスにaProxy methodを追加することです。Resourcesdraw()sprite

次に、おそらくmySprite直接アクセスする代わりに、メソッドを介してアクセスできます。次のようなメンバーがいたとします。

private ArrayList<Quad> sprites = new ArrayList<Quad>();

つまり、外部からこれらのスプライトにアクセスするには、何らかのメソッドが必要になります。ここで、他のクラスにこれらのメソッドを介して話すように強制することで、カップリングを減らしています。これは、元のクラスが別のクラスの 1 つのメソッドを知る必要があるだけで、別のクラスが作業を行うためです。次に、次のdrawSpriteようなメソッドを作成しました。

public void drawSprite(int index) // Index really is up to you {
      sprites.get(x).draw(); 
}

それよりも多くのパラメーターがある可能性があることはわかっていますが、それはクラスからの 1 つのメソッド呼び出しのみを意味するMyGLRendererため、デメテルの法則に準拠し、クラス内の結合を減らします。

于 2013-05-10T19:19:13.900 に答える
1

申し訳ありませんが、うまくいきません...

マイクが指摘したように、SomeClassメソッドのいずれかでインスタンス化されたクラスは、メソッド内にいる場合にのみ「生きている」/有効です。これは、インスタンス化されたオブジェクトがメソッドに固有であり、メソッドの外部からアクセスできないことを意味します。

考えられる解決策:

SomeClass2これに対する解決策は、メンバーをに追加することSomeClassです。このメンバーを のコンストラクターでインスタンス化すると、 がスコープ内に入るSomeClassまで存続し、使用できるようになります。SomeClassコードは次のようになります。

class SomeClass
{
    // Define the class attributes. This class can be then accessed publicly
    SomeClass2 class2

    // Constructor - Instantiate all your members here
    public SomeClass()
    {
        // Instantiate class2 in the constructor
        this.class2 = new SomeClass2();
    }

    // Your method which does what you need
    public void classMethod()
    {
        class2Object.class2Method();
    }
}

SomeClass2 は同じままです

SomeClass3 は次のようになります。

class SomeClass3
{
    public void class3Method()
    {
        SomeClass classObject = new SomeClass();

        // Call the instantiated member and then call it's method
        classObject.class2.class2Method();
    }
}

これはコンパイル/実行する必要があります。デザインについてコメントしますが、これを何に使用する予定かを確認してからコメントします。:)

于 2013-05-10T19:38:29.817 に答える
0

それは機能します(ただし、SomeClass2オブジェクトがメソッド内で宣言されており、メンバー変数としてクラス内にある必要がありますが、それはタイプミスだと思います)。

ただし、代わりにゲッターとセッターを使用することを検討します (より良い方法と見なされます)。

class SomeClass{
    private SomeClass2 class2Object = new someClass2();

    public SomeClass2 getClass2Object() { return class2Object; }
}

class SomeClass2{
    public void class2Method(){
        //Some code here
    }
}

SomeClass3{

    public void class3Method(){

        SomeClass classObject = new SomeClass();
        classObject.getClass2Object().class2Method();
    }
}
于 2013-05-10T19:11:52.797 に答える