I'm coding something like cmd in java, so I made a few commands like (hello world), , etc. All the commands are classes that implement the interface (I named it as "API"), but to identify which command is written, I use the "if" expression, so to add the new command (class), I have to write this expression every time, for instance:
if (command.equals("print")){return new Print();}
Well, that's the question, how can I write an expression once to make java identify a new command (class), no matter how much I add?
Thanks in advance;
That's the code:
This interface helps the program identify which command is written:
public interface UI {
API get();
Function<String, UI> check = command -> {
if (command.equals("print")){return new Print();}
if (command.equals("change")){return new Change();}
if (command.equals("exit")){return new Exit();}
return new NotFound();
};
static UI of(String command){
return check.apply(command);
}
}
An example of a class:
public class Print extends Backend implements API, UI{
#Override
public boolean command() {
System.out.println(string);
return true;
}
#Override
public API get() {
return new Print();
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
boolean run = true;
while (run) {
System.out.print("Java> ");
//UI
UI command = UI.of(scanner.next());
API com = command.get();
run = com.command();
}
}
}
Related
I'm new to JAVA programming, and was wondering if it's possible/how to ask the user to input what class they'd like to run and then call/run that class?
Example:
I created two classes to solve the Towers of Hanoi given (supplied by user) n amount of disks. One class solves the puzzle recursively and the other class solves the puzzle iteratively. When I am asking the user for the number of disks they'd like to use, is it possible to ask them how they would like to solve the program whether it be recursively or iteratively and then call the class that they chose?
Yes, that is possible.
This version may look a bit more complicated on first glance, but it separates the parts more clearly. The interface and the classes would usually be in separate files in real applications. Also, the static chooseSolver - method would possible be moved to a separate class named something like SolverFactory.
import java.util.Scanner;
import java.util.Set;
public class Main {
interface Solver {
void solveIt();
}
static class SuperSolver implements Solver {
public void solveIt() {
System.out.println("SuperSolver always solves anything");
}
}
static class FastSolver implements Solver {
public void solveIt() {
System.out.println("Noone beats the FastSolver");
}
}
public static void main(String[] args) {
String in = askUserForOption();
Solver s = chooseSolver(in);
s.solveIt();
}
private static String askUserForOption() {
String in;
Set<String> validOptions = Set.of("A", "B");
try (Scanner sc = new Scanner(System.in)) {
do {
System.out.print("Enter A or B: ");
in = sc.nextLine();
} while (!validOptions.contains(in));
}
return in;
}
private static Solver chooseSolver(String in) {
switch (in) {
case "A":
return new SuperSolver();
case "B":
return new FastSolver();
default:
throw new IllegalArgumentException("something went terribly wrong - an invalid option was given");
}
}
}
You can do this in a pretty straightforward manner using a common interface both solvers implement.
interface HanoiSolver {
void solve(int n);
}
// iterative solver
class IterativeHanoi implements HanoiSolver {
public void solve(int n) { ... }
}
// iterative solver
class RecursiveHanoi implements HanoiSolver {
public void solve(int n) { ... }
}
public class MainClass {
public static void main(String[] args) {
// you can change this to read input however you like
String userInput = args[0];
Integer n = Integer.parseInt(args[1]);
HanoiSolver solver;
if (userInput.equals("recursive")) {
solver = new RecursiveHanoi();
} else {
solver = new IterativeHanoi();
}
solver.solve(n);
}
}
Depends on where this code is used internally or as library package.
Internally you can use interface and then seperate out the concrete implementation.
In library , you can again let user call interface method , write implementation of that interface based on condition.
Or if you want the user to determine the algo to use during the runtime then use Reflection to decide which class's object to create.
I'm trying to create a console to handle console commands from a string.
At the moment I'm using if statements to check for each command like this:
if (command.contains("new train")) {
command = command.replace("new train ", "");
Train t = new Train();
t.setCode(command);
ServiceProvider.getTrainService().saveOrUpdate(t);
responeHandler("train " + command + " created");
}
But this isn't the best solution in my opinion.
I'm wondering whether there is already a good design pattern for problems like this?
I have looked at the builder and factory patterns but can't really decide if they are the right choice.
A Command and Factory pattern maybe?
interface Command {
void execute();
}
interface CommandFactory {
boolean canCreate(String input);
Command fromInput(String input); // or return Optional so it can be a FunctionalInterface
}
class TrainCommand implements Command {
String train;
public TrainCommand(String t) { train = t; }
public void execute() {
ServiceProvider.getTrainService().saveOrUpdate(t);
}
}
class TrainCommandFactory {
public boolean canCreate(String t) {
return t.contains("new train ");
}
public Command fromString(String c) {
return new TrainCommand(c.replace("new train ", ""));
}
}
And a Singleton Composite CommandFactory that iterates all known Command Factories:
class CommandFactories implements CommandFactory {
private static final CommandFactories INSTANCE;
private List<CommandFactory> delegates = Arrays.asList(
new TrainCommandFactory()
// others
};
public boolean canCreate(String t) {
return delegates.stream()
.filter(cf -> cf.canCreate(t))
.findAny().isPresent();
}
public Command fromString(String c) {
return delegates.stream()
.filter(cf -> cf.canCreate(t))
.findAny()
.map(CommandFactory::fromString);
}
}
You could store your commands in an array and when the user enters a command, you could find the item having the given index. The index would be meaningful and usable in a switch-case and if the item is not found, you could give a meaningful response.
Also, you could do this in a case-insensitive manner of having the keys in the array all lower characters and turning the command key to lower before the search:
protected String[] supportedCommands = {"first", "second", "third"};
public static int findCommand(String command) {
for (var i = 0; i < supportedCommands.length; i++) {
if (command.equals(supportedCommands[i])) return i;
}
return -1; //Not found
}
public static void handleCommand(String command) {
int c = findCommand(command.toLowerCase());
switch (c) {
case 1: {/*...*/} break;
default: {/*Handle Undefined command*/}
}
}
I think using defined commands is the proper way. An important issue for a command would be to be identified (matches) by the commandString and to be executed (execute). Once you have created custom Command you can register them in a List and execute them.
interface Command{
boolean matches(String commandString);
boolean execute(String commandString);
}
an Example implementation would be
CreateTrainCommand implements Command{
private final CMDSTRING = "new train";
#Override
public boolean matches(CommandString cmdStr){
if(cmdStr != null && cmdStr.toLowerCase.startsWith(CMDSTRING)){
return true;
}
return false;
}
#Override
public boolean matches(CommandString cmdStr){
if(cmdStr != null){
String train = cmdString.toLowerCase.replace(CMDSTRING, "").trim();
//here comes your command execution
Train t = new Train();
...
}
return true;//execution succesful
}
}
if you want to use these command store all commands into a List (or any other collection) and check if your command matches your input
List<Command> cmds = ...
cmds.add(new CreateTrainCommand()); //add all commands that were implemented
//or only some commands if the user has restricted access
here is how you apply the commands
String commandString = ... //from Scanner or where else
for(Command cmd: cmds){ //use streams if you're java 8
if (cmd.matches(commandString)){
boolean wasSuccesful = cmd.execute(commandString);
break;
}
}
A Map<String, Consumer<String>> could do the job to associate commands to actions.
It is not the GOF factory and command DP.
But these are fair and simple implementations of factory and command pattern.
So you should consider it too.
Map<String, Consumer<String>> actionsByCommand = new HashMap<>();
actionsByCommand.put("new train", command->{
command = command.replace("new train ", "");
Train t = new Train();
t.setCode(command);
ServiceProvider.getTrainService().saveOrUpdate(t);
responeHandler("train " + command + " created");
});
actionsByCommand.put("delete train", command->{
command = command.replace("delete train ", "");
...
});
// and so for...
You could also create a special action for invalid commands that you don't need to put in the map :
Consumer<String> invalidCommandAction = (command-> System.out.println("Invalid command. Here are the accepted commands..."));
To improve the testability and the maintainability of action classes, you could
move them into distinct classes.
Map<String, Consumer<String>> actionsByCommand = new HashMap<>();
actionsByCommand.put("new train", new NewTrainCommand());
actionsByCommand.put("delete train", new DeleteTrainCommand());
With NewTrainAction defined as :
public class NewTrainAction implements Consumer<String>{
public void accept(String command){
command = command.replace("new train ", "");
Train t = new Train();
t.setCode(command);
ServiceProvider.getTrainService().saveOrUpdate(t);
responeHandler("train " + command + " created");
}
}
And other Actions defined in the same way.
Then you can use them in this way :
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String command = scanner.nextLine();
Consumer<String> action = actionsByCommand.getOrDefault(command, invalidCommandAction);
action.accept(command);
}
If you are in the Spring world you can use
You could consider to implement
org.springframework.boot.CommandLineRunner
Each command could be executed in its own CommandLineRunne instance.
Use
org.springframework.core.env.SimpleCommandLinePropertySource
to parse your command line
Ok, so i have a kind of command manager for one of my programs.
Theres a abstract baceclass called Command which is, really simple
public abstract class Command {
protected String commandheader;
protected int requiredlevel;
protected Random rand;
public Command(RANK rank,String command)
{
commandheader = command;
requiredlevel = rank.level;
}
}
Then in each of the classes that inherit this, i just so some oop magic.
public class MyCommand extends Command {
public MyCommand()
{
super(RANK.PLAYER,"blablabla");
}
}
Then i also have a command helper class, which keeps each of these commands in a list so i can easily find if the command, is valid when i pass it in, aswell as get a lsit of all commands that are avalable.
public class CommandHelper {
public enum RANK{
PLAYER(0);
public int level;
private RANK(int i)
{
level = i;
}
}
static List<Command> commandlist;
private static void initTheCommands()
{
//Add the commands to the list here.
commandlist.add(new MyCommand());
}
//Called by my main class
public static void Init()
{
if(commandlist == null)
{
//Were safe to initalise the stuff brah.
commandlist = new ArrayList<Command>();
initTheCommands();
for(Command cmd : commandlist)
{
System.out.println("Loaded command: " + cmd.commandheader);
}
System.out.println("[INFO] Initalised the command helper");
}
else
{
System.out.println("[INFO] Command list is already populated.");
}
}
}
As of right now, this system works completely fine. But it has a flaw, for each command i or the other editors add, we have to manually add it to the list, and that seems tedious and can lead to problems as we sync files. So i was wondering, is there any way i can add each command to the list without having to manually put it there? Perhaps annotate my method, or something to just add it to the list? I seen something about reflection, but i don't think that's what i want exactly although im not sure about it. Iv never used nor made annotations before so im not sure weather or not this is plausible.
If thats what you really want to do you can do something like this...
Declare your annotation
#Target (ElementType.TYPE)
#Retention (RetentionPolicy.RUNTIME)
public #interface CommandAnnotation {
}
Annotate your commands
#CommandAnnotation
public class MyCommand {
Then check for them something like this
...
import org.reflections.Reflections;
...
public void loadCommands() {
Reflections reflections = new Reflections("com.my.package");
Set<Class<?>> allClasses = reflections.getSubTypesOf(Command.class);
for (Class<?> outerClazz : allClasses) {
CommandAnnotation annotation = outerClazz.getAnnotation(CommandAnnotation.class);
if (annotation == null)
continue;
I'm bit confused. I have the following:
public static String showInputDialog() {
Form frm = new Form();
final Command cmd = new Command("Ok");
final TextField txt = new TextField("Enter the text", null, 1024, 0);
frm.addCommand(cmd);
frm.append(txt);
frm.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c == cmd) {
return txt.getString(); // Error !!
} else {
return null; // Error !!
}
}
});
}
As you can see, I want to return the input dialog string, while the anonymous class method should return void. How can I resolve this problem?
This does not work as you expected.
I see there are already some solutions, but I feel a bit more discussion about what is actually going on might be helpful.
When you call the frm.setCommandListener(new CommandListener() { ... }) the code presents the user with a dialog where she can type in some text and submit, but the code does not stop and wait until the user finishes.
Instead the code continues to execute - without yielding the result. Only after the user finished typing and submits, you get called back to process the result - which might happen much later, or not at all.
I guess you have some code calling this method like:
public void someMethod(int foo, String bar) {
[...]
String result = MyInputForm.showInputDialog();
// do something with the result
System.out.println("hey, got a result "+ result);
[...]
}
Instead you need to reorganize this. First write a helper class handling the result:
public static class MyCallBack {
public MyCallBack(... /* here pass in what you need to process the result*/) {
... remember necessary stuff in instance variables
}
public void processResult(String result) {
// do something with the result
System.out.println("hey, got a result "+ result);
[...]
}
}
then the calling side does just:
public void someMethod(int foo, String bar) {
[...]
MyInputForm.showInputDialog( new MyCallBack(... here pass in stuff ...) );
[...]
}
and the actual code has to be changed to:
public static String showInputDialog(final MyCallBack callback) {
Form frm = new Form();
final Command cmd = new Command("Ok");
final TextField txt = new TextField("Enter the text", null, 1024, 0);
frm.addCommand(cmd);
frm.append(txt);
frm.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c == cmd) {
return callback.processResult(txt.getString());
} else {
return; // or just omit the else part
}
}
});
}
Two issues:
this way of programming feels pretty backwards, but it is really the way it works.
what feels not right is that I need to define a second helper class aside of the CommandListener. That is really not good style. I hope it can be improved, but as I do not see the complete code (which would be too much information anyway), I have to leave it to you to improve the code and get rid of the clutter. While I feel you want to have a modular, reusable input dialog helper, this might not be the best approach; better define the Form,TextField and Command directly where you need the result and get that running. Make it reusable in a second step after you get it running.
You don't need to return it if you instead do something with the String or store it somewhere, for example:
static String result;
public String commandAction(Command c, Displayable d) {
if (c == cmd) {
result = txt.getString();
} else {
result = null;
}
}
Although you'll have threading issues to deal with.
Given that CommandListener is fixed, 2 possible options are
Use a class member variable in the outer class & assign to that variable instead
private static String myText;
...
public static String showInputDialog() {
...
frm.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c == cmd) {
myText = txt.getString();
} else {
myText = null;
}
}
});
}
or Create a concrete implementation of your CommandListener and set the return value as a property of the new implementation
I would have a look at making the method/variable in this snippet non-static...
You cant return the string because you dont know when the listener will be called.
You can do something with it once you have the string though.
public static void showInputDialog() {
StringHandler sh = new StringHandler();
frm.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c == cmd) {
sh.handle(txt.getString());
} else {
sh.handle(null);
}
}
});}
public class StringHandler {
public void handle(String s){
// Do something with that string.
}
}
say I have three methods
method1()
method2()
method3()
and I have the user input a number corresponding to which method they want to run, is there a way to run it directly from their input? i.e. instead of having an if statement along the lines of
System.out.println("Which method would you like to run? 1/2/3");
String input = reader.readLine();
if(input == 1){method1();}
if(input == 2){method2();}
...
etc. and instead be able to have something like
System.out.println("Which method would you like to run? 1/2/3");
String input = reader.readLine();
method(input)();
?
Yes you could achieve that by using an interface as follows:
interface A {
void run();
}
public void method1() {}
public void method2() {}
public void mainMethod(String[] args) {
// Initialise the method map - note, you only have to do this once
// So, this initialisation code can go into a constructor
// And mothodMap can be declared as a final instance variable.
A methodOne = new A() { #Override public void run() { method1(); } };
A methodTwo = new A() { #Override public void run() { method2(); } };
Map<Integer, A> methodMap = new HashMap<>();
methodMap.put(1, methodOne);
methodMap.put(2, methodTwo);
Integer input = /* get it from user*/ 1;
A aMethod = methodMap.get(input);
aMethod.run();
}
No, not unless you use reflection. Java doesn't have function pointers, otherwise you could index to the appropriate function in an array. But what's wrong with if statements? They're more readable and secure..
If you're looking for a future-proof, more abstract solution, consider a strategy pattern:
// strategy
interface CommandMethod {
void runMethod();
}
// for every method 1 .. n
class CmdMethod1() implements CommandMethod {
void runMethod() {
// concrete implementation
}
}
// initialization ----------------
Map<String, CommandMethod> cmds = new HashMap<String, CommandMethod>();
cmds.put("1", new CmdMethod1());
// .. etc ..
cmds.put("n", new CmdMethodN());
// at the prompt:
System.out.println("Which method would you like to run? 1/2/3/.../n");
String input = reader.readLine();
cmds.get(input).runMethod(); // more like what you're going for ?
Not without having an if or switch statement (or reflection like paislee pointed out). If you wanted to do something like method(input); you would need the if/switch statement in another method:
....
String input = reader.readLine();
method(input);
}
private void method(int input) {
if (input == 1) {method1();}
if (input == 2) {method2();}
}
There's no way to do this. However, you can use if-statements or switch-case statements to make the "redirection" process less cumbersome. You might also consider creating a wrapper function to accept the user input to make your code cleaner.
The standard way of accomplishing this is to create a "functor"
public interface Functor
{
public void execute();
}
public class Method1 implements Functor
{
public void execute() { /* do something */ }
}
etc...
private Functor[] f = { new Method1(), new Method2(), new Method3() };
...
// Execute the method selected by i
f[i].execute();
Also take a look at the Callable interface
Just to update this. Another way this can be implemented is by using switch-case in a while true loop. And using scanner object static Scanner scanner = new Scanner(System.in); user input.
while(true){
System.out.print("Input: ");
int option = scanner.nextInt();
switch(option){
case 1 -> method1();
case 2 -> method2();
}
}
do remember to include a way to exit the while loop in any of the methods.