0

编辑:已编辑以提供更具体的代码

正如你所看到的,我的精灵图打破了这个规则。

如果有人可以根据我下面的代码通过伪代码的方式进行解释,我将不胜感激(这是因为我已经阅读了很多关于此规则的解释,但我仍然不明白为什么这是一个问题或如何做我需要在不违反此规则的情况下做:-()

1)为什么这会导致我的代码出现问题?

&

2)请解释做我正在尝试做的事情的另一种方法(同时保留一个单独的资源类,专门用于加载我的资源和创建我的精灵对象)。


通过 2 个或更多类对象访问对象有什么问题吗?我将通过一些代码进行解释:

这里我有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

Why it's bad to have several chained method calls

The law this violates

This violates a coding practice known as the law of demeter. This law states that you should only talk to those classes "next to you".

Why this is a bad thing

The reason for this is because, by calling methods in several other classes, your class needs to know about those methods, and depends on those methods changing. This is called close coupling. If the methods change, you need to change lots of code in other classes. This is called "Shotgun Surgery" and isn't a desirable feature in a program!

A possible solution

Look into the proxy design pattern. It's primarily designed to provide an interface to another class, and it might help you here. Perhaps by having a reference to both objects, this class can provide a common interface for all methods to talk via and reduce the coupling between the classes.

Edit to help with your example

Your example isn't actually that bad. You get an object, and you make a method call on it. The dependency comes in one form: If you remove the mySprite field from your class, your code won't work, and if you remove the draw method from your sprit it won't work. To me, the easiest solution is to add a Proxy method to your Resources class, called draw() that accepts a sprite as an argument.

Secondly, perhaps instead of accessing mySprite directly, you can put it through a method. Let's say you had a member that looked like this:

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

This means that in order to gain access to these sprites from the outside, you would need to have some sort of method. Now, by forcing other classes to talk via these methods, you're reducing coupling. This is because the original class only needs to know the one method in another class, and the other class will do the work. Then you wrote a drawSprite method that looked something like:

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

Now I know it might have more parameters than that, but it only means one method call from your MyGLRenderer class, hence conforming to the law of demeter, and reducing coupling in your classes.

于 2013-05-10T19:19:13.900 回答
1

对不起,但它不会工作......

正如 Mike 指出的那样,在任何SomeClass's 方法中实例化的类只有在您在方法内部时才“活动”/有效。这意味着实例化的对象是特定于方法的,不能在方法之外访问。

一个可能的解决方案:

解决方案是添加一个SomeClass2成员到SomeClass. 如果您在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对象是在方法中声明的,它应该作为成员变量在类中,但我认为这是一个错字)。

但我会考虑改用 getter 和 setter(这被认为是更好的做法):

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 回答