Reputation: 33
To help me learn Java and programming concepts, I'm writing a bot that will solve the puzzles in the game PuzzleFreak .
I've made the controller for the game a singleton, since there should be only one. However, now I have Controller.getInstance()
peppered everywhere. How can I make this less verbose? Is a Singleton even the way to go here?
I could wrap the controller methods in default methods so that I could just call click(x,y)
in the Player
implementations, but that feels wrong.
Below I have the Player interface and an example implementation.
Player.java:
public interface Player {
default void giveUp() {
Controller.getInstance().click(new Rectangle(704, 545, 64, 18));
Controller.getInstance().delay(0.1);
Controller.getInstance().click(new Rectangle(704, 545, 64, 18));
}
default void play() {
giveUp();
}
}
StartupPlayer.java:
public class StartupPlayer implements Player {
public void play(){
Controller.getInstance().click(60, 278);
Controller.getInstance().delay(0.5);
Controller.getInstance().type("KevinBot");
Controller.getInstance().delay(0.5);
Controller.getInstance().click(400, 463);
}
}
Upvotes: 3
Views: 129
Reputation: 56477
In the interface, you could get the controller through a getter:
public interface Player {
default void giveUp() {
Controller controller = getController();
controller.click(new Rectangle(704, 545, 64, 18));
controller.delay(0.1);
controller.click(new Rectangle(704, 545, 64, 18));
}
default void play() {
giveUp();
}
default Controller getController() {
return Controller.getInstance();
}
}
Then, the implementation class also uses the getter:
public class StartupPlayer implements Player {
public void play(){
Controller controller = getController();
controller.click(60, 278);
controller.delay(0.5);
controller.type("KevinBot");
controller.delay(0.5);
controller.click(400, 463);
}
}
This way, it's easier to change the decision that it's a singleton later on.
Also, if you'll be calling lots of controller methods in succession, you might consider making it a fluent interface, and renaming the getter simply to controller
(I think it makes it more fluent as well), you'd have:
public interface Player {
default void giveUp() {
controller().
click(new Rectangle(704, 545, 64, 18)).
delay(0.1).
click(new Rectangle(704, 545, 64, 18));
}
default void play() {
giveUp();
}
default Controller controller() {
return Controller.getInstance();
}
}
public class StartupPlayer implements Player {
public void play(){
controller().
click(60, 278).
delay(0.5).
type("KevinBot").
delay(0.5).
click(400, 463);
}
}
This cuts down on the verbosity even further...
And, if the default implementation you provide in the interface for play
is really meant to be overridden every time, you should consider keeping it abstract. The method giveUp
would still be available for implementing classes to use.
Upvotes: 1
Reputation: 1150
You can have an public Enum called SigletonEnum with a single instance called INSTANCE. This is a singleton.
As this is an enum, it is not required to be instantiated.And then in the application you can call it as
SingletonEnum.INSTANCE.doSomething();
Upvotes: 0
Reputation: 25429
Set it to a variable in the target context(s) (class); even in a variable it's the same instance. Just a different reference to the same instance.
Upvotes: 0
Reputation: 4638
Just declare a local controller and call getInstance()
once:
For example:
public class StartupPlayer implements Player {
public void play(){
Controller controller = Controller.getInstance()
controller.click(60, 278);
controller.delay(0.5);
controller.type("KevinBot");
controller.delay(0.5);
controller.click(400, 463);
}
}
Upvotes: 2