我有一个Gui类,它是一个Singleton,因为许多其他类必须使用Gui的方法,并且任何时候都应该只有一个Gui实例。
我也有Player Class(有点像Audioplayer),也是Singleton。
当我启动Gui时,我告诉玩家获取当前状态(这会创建一个新的玩家实例)并将其显示在Gui上。因此,玩家创建了一个新的Gui实例,因为Gui的构造函数尚未完成。
因此,这会产生无休止的递归。 我想保持单身人士模式。 有没有办法将getInstance()中的实例设置为“null”以外的其他内容,即使Constructur尚未完成?
由于
答案 0 :(得分:2)
我可能会avoid the singleton pattern altogether。正如您所发现的那样,它使控制创建生命周期变得困难。
相反,我会创建一个GuiManager
,它会创建Gui
,然后将其注入需要了解它的相应组件中?这称为inversion of control(或dependency injection),避免了对全局状态的需要。好处包括使测试变得容易(因为周围的框架控制了对象的生命周期),并且这些对象的创建是可预测的。
答案 1 :(得分:0)
创建初始化函数
public class Gui
{
public static Gui instance;
public static Gui getInstance()
{
if(instance == null)
{
instance = new Gui();
instance.initialize();
}
return instance;
}
private Gui()
{
}
private initialize()
{
// do constructor work here
}
}
答案 2 :(得分:0)
我会使用静态初始化块。在构造类时调用它。而不是在创建对象时。它只召唤一次。 see more
答案 3 :(得分:0)
此递归是更一般的设计问题的症状。您当然可以尝试通过从构造函数中“泄漏”实例引用来解决它,或者将“构造”推迟到稍后调用的某些初始化方法(可能是懒惰的),但我不建议使用 1 。
为什么GUI 和 Player类必须是单身人士并且必须彼此了解,更具体地说,在构建期间必须彼此了解?除了'更方便'之外还有一个理由可以全局访问某个对象吗?并非方便并不重要,但通常不应该是设计决策的唯一原因。
更好的方法是完全摆脱单身人士,因为没有真正的理由不能同时存在两个播放器和GUI实例。当然,你的程序可能只有一个,但这不是Singletons的目的。
此外,您应该只在一个方向上具有依赖性。试着想想没有对方可以存在什么,什么不能存在。我认为GUI应该依赖于播放器,因为你可能会想象有一个没有GUI的播放器,但没有播放器的GUI根本就没有意义。因此,您首先构造一个Player,然后构造一个GUI并将其传递给它所运行的Player实例。如果您认为需要从Player内的任何位置访问GUI实例,您应该重新考虑设计并尝试使这些对象更加独立。这通常可以通过使用Observer模式完成,并让GUI监听发生的更改/操作/内容。这样,您的应用程序代码根本不了解GUI。但是,在GUI中,您可以根据需要传递GUI实例。
关于引入'经理'对象或工厂模式的想法:它可能是有用的,但你可以做到我上面所说的所有内容,如果没有它,仍然有一个理智的设计。我通常会反对'经理'课程,因为他们倾向于做太多的事情,而且通常是伪装的单身人士。但是,工厂可能很有用,但前提是您要将实际构造的东西与其使用分离,例如允许稍后实现不同类型的GUI。
所以一个简单的实现看起来像这样:
public static void main(...) {
Player player = new Player();
// maybe some other stuff to configure/set up the player
GUI gui = new GUI(player);
gui.show(); // or something similar
}
如果你想使用工厂,你当然可以用你之前必须获得的工厂来代替new ...
表达式。
1为什么呢?好吧,例如,如果您成功构建 GUI会发生什么,但稍后无法初始化它,例如抛出异常?您需要某种方法将这种“无效”状态传达给已经获得GUI实例的所有对象。此外,您必须确保在初始化之前没有人使用GUI实例。