I'm currently working on my first larger java project (a game) and I'm having a bit of an organisation issue already with only a few (~40) classes.
I'm organizing my game something like this:
我目前正在开发我的第一个更大的java项目(一个游戏),我只有一些组织问题,只有几个(~40个)类。我正在组织我的游戏:
That seems quite organized to me as every smaller class is categorized in a larger class. Obviously classes like the ObjectHandler
or the Model
will contain more classes, otherwise they'd be useless.
这对我来说似乎非常有条理,因为每个小班级都被归类为更大的班级。显然,像ObjectHandler或Model这样的类将包含更多的类,否则它们将毫无用处。
Now my issue is: When I'm trying to access the current PlayerSettings
from the DynamicObjects
in the GUI
(for example when I'm trying to get the position of the player in order to draw it on the canvas), I'd have to create a long path like this:
现在我的问题是:当我尝试从GUI中的DynamicObjects访问当前的PlayerSettings时(例如,当我试图获取播放器的位置以便在画布上绘制它时),我有创建这样的长路径:
int x = gui.engine.model.objHandler.player.playerSettings.getX();
(For that purpose I set most parameters public
. I could also make them accessible with get()
-methods, but that seems even more unorganized to me)
(为此目的,我将大多数参数设置为public。我也可以使用get() - 方法访问它们,但这对我来说似乎更无组织)
My question is - does that look any normal or are there any better ways to solve this organisation issue?
我的问题是 - 这看起来是正常的还是有更好的方法来解决这个组织问题?
3 个解决方案
#1
The short answer is that - no, you wouldn't want a situation where you have to de-reference six objects in order to get to the data you need.
简短的回答是 - 不,你不会想要一个必须取消引用六个对象才能获得所需数据的情况。
This probably means something is wrong with how you broke up your data and functionality into classes. You would generally want to group together objects that have to talk to each other.
这可能意味着您将数据和功能分解为类的方式有问题。您通常希望将必须相互通信的对象组合在一起。
One practical advice is that your objects do not have to form a tree. It may make sense for the DynamicObjects to hold a reference to the PlayerSettings. This is just an example: I don't know what make sense in your application, I am just trying to point out that you don't have to think of object relationships as a tree.
一个实用的建议是,您的对象不必形成树。 DynamicObjects保持对PlayerSettings的引用可能是有意义的。这只是一个例子:我不知道你的应用程序中有什么意义,我只想指出你不必将对象关系视为一棵树。
And regarding get methods vs. public members: it's a Java convention to use private variables with getters and setters. It has to do with maintainability and changing the implementation in the feature. Even if that doesn't convince you, I think it's a good thing to acquire the style standards that are common in Java coding.
关于get方法与公共成员:将私有变量与getter和setter一起使用是一种Java约定。它与可维护性和更改功能中的实现有关。即使这不能说服你,我认为获得Java编码中常见的样式标准是件好事。
#2
As the Law of Demeter suggests, having your dependencies loosely coupled and as ignorant of other classes as possible, helps to make your application more maintainable. Reducing the coupling between the components enables you to rapidly refactor or change individual modules/classes.
正如Demeter法所建议的那样,让你的依赖关系松散耦合并尽可能地忽略其他类,有助于使你的应用程序更易于维护。减少组件之间的耦合使您能够快速重构或更改单个模块/类。
Your GUI shouldn't know where the player settings object comes from, nor should there be a reason for the GUI to fetch the information itself -- instead, the object should be injected to the GUI. There are many frameworks that enable Dependency injection for you, such as Google Guice, but you can also implement a simplistic version yourself by simply providing the object as parameter to the GUI, into the constructor or to a specific initialization method.
您的GUI不应该知道播放器设置对象的来源,也不应该知道GUI本身获取信息的原因 - 相反,应该将对象注入GUI。有许多框架可以为您启用依赖注入,例如Google Guice,但您也可以通过简单地将对象作为参数提供给GUI,构造函数或特定的初始化方法来实现简化版本。
public class MyGUI {
private PlayerSettings settings;
//...
public void initialize(PlayerSettings settings) {
this.settings = settings;
}
//...
}
Also, try to organize the code into meaningful packages and reduce the visibility of the classes within a package so that they cannot be accessed from "far away". Only expose a public API outside the package for others to use and see. The same applies for methods and fields within classes; you should not use public
fields (aside from constants). Expose as little information outside as possible and you will be able to refactor the code within you class (or package) without breaking code that's "far away".
此外,尝试将代码组织到有意义的包中,并降低包中类的可见性,以便无法从“远处”访问它们。仅在包外部公开API以供其他人使用和查看。这同样适用于类中的方法和字段;你不应该使用公共字段(除了常量)。尽可能少地暴露在外面的信息,您将能够重构您的类(或包)中的代码,而不会破坏“远离”的代码。
#3
A quick way to clean up dependency messes like this is to use Google Guava's EventBus. You can use it to post events and then anything subscribing to those events will act on them, all without any components knowing each other or where events come from. Its a quick way to decouple effectively and manage dependencies efficiently.
清理像这样的依赖混乱的一种快速方法是使用Google Guava的EventBus。您可以使用它来发布事件,然后订阅这些事件的任何事情都会对它们起作用,所有事件都没有任何组件相互了解或事件来自何处。它是一种快速有效地解耦并有效管理依赖关系的方法。
If you want something even more elegant, look at reactive programming and explore RxJava.
如果你想要更优雅的东西,看看反应式编程并探索RxJava。
#1
The short answer is that - no, you wouldn't want a situation where you have to de-reference six objects in order to get to the data you need.
简短的回答是 - 不,你不会想要一个必须取消引用六个对象才能获得所需数据的情况。
This probably means something is wrong with how you broke up your data and functionality into classes. You would generally want to group together objects that have to talk to each other.
这可能意味着您将数据和功能分解为类的方式有问题。您通常希望将必须相互通信的对象组合在一起。
One practical advice is that your objects do not have to form a tree. It may make sense for the DynamicObjects to hold a reference to the PlayerSettings. This is just an example: I don't know what make sense in your application, I am just trying to point out that you don't have to think of object relationships as a tree.
一个实用的建议是,您的对象不必形成树。 DynamicObjects保持对PlayerSettings的引用可能是有意义的。这只是一个例子:我不知道你的应用程序中有什么意义,我只想指出你不必将对象关系视为一棵树。
And regarding get methods vs. public members: it's a Java convention to use private variables with getters and setters. It has to do with maintainability and changing the implementation in the feature. Even if that doesn't convince you, I think it's a good thing to acquire the style standards that are common in Java coding.
关于get方法与公共成员:将私有变量与getter和setter一起使用是一种Java约定。它与可维护性和更改功能中的实现有关。即使这不能说服你,我认为获得Java编码中常见的样式标准是件好事。
#2
As the Law of Demeter suggests, having your dependencies loosely coupled and as ignorant of other classes as possible, helps to make your application more maintainable. Reducing the coupling between the components enables you to rapidly refactor or change individual modules/classes.
正如Demeter法所建议的那样,让你的依赖关系松散耦合并尽可能地忽略其他类,有助于使你的应用程序更易于维护。减少组件之间的耦合使您能够快速重构或更改单个模块/类。
Your GUI shouldn't know where the player settings object comes from, nor should there be a reason for the GUI to fetch the information itself -- instead, the object should be injected to the GUI. There are many frameworks that enable Dependency injection for you, such as Google Guice, but you can also implement a simplistic version yourself by simply providing the object as parameter to the GUI, into the constructor or to a specific initialization method.
您的GUI不应该知道播放器设置对象的来源,也不应该知道GUI本身获取信息的原因 - 相反,应该将对象注入GUI。有许多框架可以为您启用依赖注入,例如Google Guice,但您也可以通过简单地将对象作为参数提供给GUI,构造函数或特定的初始化方法来实现简化版本。
public class MyGUI {
private PlayerSettings settings;
//...
public void initialize(PlayerSettings settings) {
this.settings = settings;
}
//...
}
Also, try to organize the code into meaningful packages and reduce the visibility of the classes within a package so that they cannot be accessed from "far away". Only expose a public API outside the package for others to use and see. The same applies for methods and fields within classes; you should not use public
fields (aside from constants). Expose as little information outside as possible and you will be able to refactor the code within you class (or package) without breaking code that's "far away".
此外,尝试将代码组织到有意义的包中,并降低包中类的可见性,以便无法从“远处”访问它们。仅在包外部公开API以供其他人使用和查看。这同样适用于类中的方法和字段;你不应该使用公共字段(除了常量)。尽可能少地暴露在外面的信息,您将能够重构您的类(或包)中的代码,而不会破坏“远离”的代码。
#3
A quick way to clean up dependency messes like this is to use Google Guava's EventBus. You can use it to post events and then anything subscribing to those events will act on them, all without any components knowing each other or where events come from. Its a quick way to decouple effectively and manage dependencies efficiently.
清理像这样的依赖混乱的一种快速方法是使用Google Guava的EventBus。您可以使用它来发布事件,然后订阅这些事件的任何事情都会对它们起作用,所有事件都没有任何组件相互了解或事件来自何处。它是一种快速有效地解耦并有效管理依赖关系的方法。
If you want something even more elegant, look at reactive programming and explore RxJava.
如果你想要更优雅的东西,看看反应式编程并探索RxJava。