5

I'm exploring possibilities of static and default methods introduced in java 8.

I've an interface that has 2 default methods that do construct a command, that I run on server through ssh to do some simple tasks remotely. Moving mouse requires 2 arguments: x and y position of the mouse.

public interface Robot {

    default String moveMouse(int x, int y) {
        return constructCmd("java -jar move_mouse.jar " + x + " " + y);
    }

    default String clickLeft() {
        return  constructCmd("java -jar click_left.jar");
    }

    static String constructCmd(String cmd) {
        return "export DISPLAY=:1.0\n" +
                "cd Desktop\n" +
                cmd;
    }
} 

I've multiple enums with values preset, I could potently combine all enums into one and not use interface what so ever, however that enum would contain hundreds or thousands of values and I want to keep it somewhat organised, so I've split evertying in multiple enums.

I want all enums to share same methods so I figured I'll give default methods in an interface a shot.

public enum Field implements Robot {

    AGE_FIELD(778, 232),

    NAME_FIELD(662, 280);

    public int x;
    public int y;

    Field(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

So I can get String commands by:

Field.AGE_FIELD.clickLeft();
Field.AGE_FIELD.moveMouse(Field.AGE_FIELD.x, Field.AGE_FIELD.y);

However moveMouse looks really bad to me and I think it should be somehow possible to use enum's values by default.

Anyone has a a nice solution for such problem?

1
  • 4
    This seems to be a conceptual problem. What you want is an interface with methods void moveMouse(), int getMouseTargetX() and int getMouseTargetY(). Your current design asks for the specific x- and y-Coordinates. My proposal assumes that the object has some attributes, defininig the x- and y- Coordinates. My proposal is more like an extension to your already existing system than a replacement. Your interface would be used for the component to actually move the mouse, whereas my interface would be used by components, that call the component that actually moves the mouse. Commented Oct 26, 2016 at 9:22

2 Answers 2

5

The problem is your architecture. On the one hand, you have a layer that actually executes the mouse-movement (represented by your Robot interface). Now, you need a layer that produces mouse-movement and sends it to a Robot to execute this mouse-movement. Let's call the interface defining this layer MouseTarget (fits your example nicely):

public interface MouseTarget {
    int getTargetX();
    int getTargetY();

    default void moveMouseHere(Robot robot) {
        robot.moveMouse(this.getTargetX(), this.getTargetY());
    }
}

This interface represents one mouse-movement to one target. As you see the moveMouseHere(Robot robot) method expects a Robot to send the movement to (which does the actual work). Now, all what is left is to adapt your Fields enum:

public enum Fields implements MouseTarget {

    AGE_FIELD(778, 232), NAME_FIELD(662, 280);

    public int targetX;
    public int targetY;

    Fields(int targetX, int targetY) {
        this.targetX = targetX;
        this.targetY = targetY;
    }

    @Override
    public int getTargetX() {
        return targetX;
    }

    @Override
    public int getTargetY() {
        return targetY;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Modifier 'public' is redundant for interface methods
3

As you may want to have several implementations of Robot, I would clearly not proceed as you do, I would rather provide a Robot instance to the methods of your enum instead of implementing the interface Robot, it would then be much more flexible and easier to test.

The enum Field

public enum Field {

    ...

    public String moveMouse(Robot robot) {
        return robot.moveMouse(x, y);
    }

    public String clickLeft(Robot robot) {
        return robot.clickLeft();
    }
}

Even if it is not strictly the Strategy pattern, it is globably the same approach.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.