开发者

Most efficient way of going about programming this in Java

Okay le开发者_如何学编程ts say you have a simple program which took letter a-z, and if you typed in "c" it would do something, for example "e" might add 2 random numbers, "h" displayed the word "hello", "x" displayed the time etc.

Now how i'm attempting to go around this by having 26 different methods, one for each letter and then a main body of code, which scans for the the users input then calls the appropriate method.

Now theirs obviously 100's of ways of going around this but the main two I'm thinking off is you could have 26 if's or a switch statement(Example, if(userInput.equals("a")) then call method a etc). Or another way I'm thinking off is having the methods labeled a-z and then lets say the user enters "f" instead of checking which letter it is it instead trusts the user and calls exactly the letter they've typed in.

for example:

-> User enters Y

userInput = y;

userInput(); - (which would essentially be calling y() which is a method name).

I believe there is a way to do this using "Reflection" from reading around here but I've heard to avoid premature optimization but in this case wouldn't it be the most logical thing to do?


The ways I see:

  • 1) setup a big if/else if tree to check user input
  • 2) setup some flaky, unstable and slow Reflection stuff
  • 3) Use a Map where 'String' would be the letter and the CmdHandler would be a class that has a function to be called. (Command Pattern)

the #3 is a bit more architecture for such a simple example, but it lends itself to scaling better.

EDIT: Quick n Dirty Example

public class Testing {
    public static void main(String[] args) {
    CmdHandler ch = null;

    /* Setup & populate our map */
    HashMap<String, CmdHandler> cmdMap = new HashMap<String,CmdHandler>();

    ch = new AKeyHandler();
    cmdMap.put(ch.getCmd(), ch);

    ch = new BKeyHandler();
    cmdMap.put(ch.getCmd(), ch);
    /* ..etc.. */

    /* Actually use the system now! */
    String input = "";
    input = "a"; /* Get our input from... whereever */

    /* Do any input validation/manipulation here */

    CmdHandler handler = cmdMap.get(input.toUpperCase());
    if (handler != null)
        handler.doWork();
    else
        System.err.println("Egads!  A null!");

    }

public static abstract class CmdHandler {
    private final String cmd;
    public CmdHandler(String cmd) {
        super();
        this.cmd = cmd.toUpperCase();
    }
    public String getCmd(){
        return this.cmd;
    }
    public abstract void doWork();
}
public static class AKeyHandler extends CmdHandler{     
    public AKeyHandler() {
        super("a");
    }
    public void doWork() {
        System.out.println("Executing the A Key cmd doWork()");
    }
}
public static class BKeyHandler extends CmdHandler{     
    public BKeyHandler() {
        super("b");
    }
    public void doWork() {
        System.out.println("Executing the B Key cmd doWork()");
    }
}

/* ...etc... */

}


I would consider using an enum.

enum Letter{
    A("a"){
        @Override
        void foo(){
            // do stuff
        }
    }, 
    B("b"){
        @Override
        void foo(){
            // do stuff
        }
    },
    .
    .
    .
    Z("z"){
        @Override
        void foo(){
            // do stuff
        }
    };

    private final String text;
    Letter(final String text){
        this.text = text;
    }

    abstract void foo();
    public static final Letter getInstance(final String s){
        for(Letter l: Letter.values()){
            if(s.equalsIgnoreCase(l.text)){
                return l;
            }
        }

        return null;
    }
}

This way you can simply get the user input, invoke Letter.getInstance(...) and then get the appropriate Letter instance. And then from there, you simply invoke foo() on the Letter instance, which will do something specific to that letter.


Okay, first off, reflection is actually pretty slow. It requires the program to examine it's own code (although that may not be the source of the slowness).

Do you really need 26 different methods? that smells a bit odd to me. Is there any repeat code in those methods? if yes, you should find that commonality and have a switch or set of if statements to manage the letter-specific code. This actually would be more efficient, and will create a smaller footprint for your application.

The main problem with worrying about switch vs. if efficiency, as I see it, is that unless you're writing mission-critical software, or extremely optimized something (which you probably won't be writing in java), and the code in question is called thousands of times a second, the difference is negligible.

Assuming you actually need those 26 different methods, Dave Newton's answer is probably what you want.


Reflection would be an option but you would be at the risk of a user entering a function suffix which does not exist. If using a database is not an option, your best bet would probably be to instantiate a Map with the letters as the keys and the display result as the value and call the get(Object key) method with the user input as the key. If the result is null (user did not enter a letter) you can handle it appropriately.

If the values need to be calculated when the user enters a letter, you can fill the map with objects implementing some interface with a "process" method. When you pull the value out you will just need to call the process method. Notice the use of the anonymous class, as this would probably be best in this situation.

map.put("a", new Processor(){
     @Override
     public String process(){
          return "someString";
     }
}

where Processor is some interface you have created.


This is the Command Pattern (Edit: deleted all humor; thank goodness for the humor patrol). There are any number of ways to implement it, but the simplest is a map of command handlers.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜