Refactor java code - java

Okay guess this question looks a lot like:
What is the best way to replace or substitute if..else if..else trees in programs?
consider this question CLOSED!
I would like to refactor code which looks something like this:
String input; // input from client socket.
if (input.equals(x)) {
doX();
} else if (input.equals(y)) {
doY();
} else {
unknown_command();
}
It is code which checks input from socket to perform some action, but I don't like the if else construction because every time a new command is added to the server (code) a new if else has to be added which is ugly. Also when deleting a command the if else has to be modified.

Collect those commands in a Map<String, Command> where Command is an interface with an execute() method.
Map<String, Command> commands = new HashMap<String, Command>();
// Fill it with concrete Command implementations with `x`, `y` and so on as keys.
// Then do:
Command command = commands.get(input);
if (command != null) {
command.execute();
} else {
// unknown command.
}
To get a step further, you could consider to fill the map dynamically by scanning for classes implementing a specific interface (Command in this case) or a specific annotation in the classpath. Google Reflections may help lot in this.
Update (from the comments) You can also consider combining the answer of Instantsoup with my answer. During the buildExecutor() method, first get the command from a Map and if the command doesn't exist in Map, then try to load the associated class and put it in the Map. Sort of lazy loading. This is more efficient than scanning the entire classpath as in my answer and creating it everytime as in Instantsoup's answer.

One way could be to have an interface ICommand that is the general contract for a command, e.g.:
public interface ICommand {
/** #param context The command's execution context */
public void execute(final Object context);
public String getKeyword();
}
And then you could use Java's SPI mechanism to auto-discover your various implementations and register them in a Map<String,ICommand> and then do knownCommandsMap.get(input).execute(ctx) or something alike.
This practically enables you to decouple your service from command implementations, effectively making those pluggable.
Registering an implementation class with the SPI is done by adding a file named as the fully qualified name of your ICommand class (so if it's in package dummy the file is going to be META-INF/dummy.ICommand within your classpath), and then you'll load and register them as:
final ServiceLoader<ICommand> spi = ServiceLoader.load(ICommand.class);
for(final ICommand commandImpl : spi)
knownCommandsMap.put(commandImpl.getKeyword(), commandImpl);

How about interfaces, a factory, and a little reflection? You will still need to handle exceptions on bad input, but you would always need to do this. With this method, you just add a new implementation of Executor for a new input.
public class ExecutorFactory
{
public static Executor buildExecutor(String input) throws Exception
{
Class<Executor> forName = (Class<Executor>) Class.forName(input);
return (Executor) executorClass.newInstance();
}
}
public interface Executor
{
public void execute();
}
public class InputA implements Executor
{
public void execute()
{
// do A stuff
}
}
public class InputB implements Executor
{
public void execute()
{
// do B stuff
}
}
Your code example then becomes
String input;
ExecutorFactory.buildExecutor(input).execute();

Building the Command patten upon an enum class can reduce some of the boilerplate code. Let's assume that x in input.equals(x) is "XX" and y in input.equals(y) is "YY"
enum Commands {
XX {
public void execute() { doX(); }
},
YY {
public void execute() { doY(); }
};
public abstract void execute();
}
String input = ...; // Get it from somewhere
try {
Commands.valueOf(input).execute();
}
catch(IllegalArgumentException e) {
unknown_command();
}

You say that you're processing input from a socket. How much input? How complex is it? How structured is it?
Depending on the answers to those questions, you might be better off writing a grammar, and letting a parser generator (eg, ANTLR) generate the input-processing code.

Related

How to implement a Java method, that will call another method, based on the name of the calling class?

We have a Java class, WebCenterGrid. This class is full of methods to do things in a grid such as finding a row, finding a cell value, sorting a column. We have several classes that use this class. The classes using it all refer to different grids, but the functionality is the same.
The only thing that differs is how to create the grid. Some classes do a search which populates the grid (search also refreshes). Some do an updateList() to update the grid, etc.
I would like to add a method to WebCenterGrid to refresh the grid. The problem is as I said each method has a different name.
I somehow want to pass into WebCenterGrid the name of a method to call to do the refresh. I have done some searches and found something about lambda which I did not really understand.
I haven't used C++ in a while but there was some way to pass a method into those methods. This class is in Java not C++, but is there some sort of understandable equivalent?
public class WebCenterGrid {
....
....
public void refresh(Method meth) {
meth();
}
}
Basically, there are two ways.
One is to use reflection, this means: relying on runtime type information, commonly derived from raw strings. Like saying: I have some object of class X, and I want to invoke the method named "doTheFoo()" on that object.
See here for all the glory details.
A slightly better way is to use the MethodHandle class, instead of the "raw" reflection Method class. See here for handles.
But then: reflection is happening at runtime. Your code compiles fine, but if you get any detail wrong, it blows up at runtime.
Thus I suggest looking into lambdas, based on Function, see here.
Instead of having a Method parameter, accept an Interface, and the implementation will define what will be called.
You can use lambdas here as well if you'll define your interface as Functional Interface.
Example:
public class Main {
public static void main(String[] args) {
act(new Run());
act(new Swim());
// Passing a body of the function you want to execute
act(() -> System.out.println("walking"));
}
public static void act(Action action) {
action.act();
}
}
#FunctionalInterface
interface Action {
void act();
}
class Run implements Action {
#Override
public void act() {
System.out.println("running");
}
}
class Swim implements Action {
#Override
public void act() {
System.out.println("swimming");
}
}
Output:
running
swimming
walking
If you have predefined refresh logic, you can create association resolver based on mapping which will help you to define proper service based on some conditions.
public class Main {
static Map<ActionType, Action> actionResolver = new HashMap<>();
// Static init is just for brevity sake
static {
actionResolver.put(ActionType.RUN, new Run());
actionResolver.put(ActionType.WALK, new Walk());
actionResolver.put(ActionType.SWIM, new Swim());
}
public static void main(String[] args) {
act(ActionType.RUN);
act(ActionType.WALK);
act(ActionType.SWIM);
}
public static void act(ActionType actionType) {
Action action = actionResolver.get(actionType);
if (action == null)
throw new IllegalArgumentException("ActionType was not registered");
action.act();
}
}
enum ActionType {
RUN,
SWIM,
WALK
}
Output is the same as above.
Well, since we can't see any of your code, I'll suggest the following solution, that's based on my personal assumption about how your code works.
Please keep in mind that this method is not so scale-able and pretty inefficient if you have 100 different ways of creating grids.
However, if you have (e.g. 3) types of such ways for example, you can use constants!
See below:
public class WebCenterGrid {
//Declare constants with meaningful names for grid creation (add more as you like)
public static final int DEEP_COPY=1, SEARCH=2, REBUILD=3;
public void makeDeepCopy(){
//implementation goes here..
}
public void searchAndPopulate(){
//implementation goes here..
}
public void rebuildGrid(){
//implementation goes here..
}
public void refresh(int operation) {
switch(operation) {
//based on 'operation', call appropriate method!
case DEEP_COPY: this.makeDeepCopy(); break;
case SEARCH: this.searchAndPopulate(); break;
case REBUILD: this.rebuildGrid(); break;
//you can have a default operation for any parameter that is not
//in the list of our defined constants(i.e. the number 143)
default: simpleRefresh(); break;
}
}
}
So what makes the above solution work?
Basically, when you call refresh(int operation) from one of your other classes, you need to pass an int as a parameter. That integer is one of the constants defined at the very top of the class. According to which constant was passed, the switch case will determine which method to call.
EXAMPLE (Let's say that AwesomeGridCreator is a class that when it calls refresh(), in order to update a grid, it has to do a search and then populate the grid (like you mention in your question).
We name an integer (for simplicity) SEARCH_POPULATE and we give it ANY value we want. For example 286.
We can then use that constant from any other class, because we don't care what its value is (in this case 286, but the functionality it provides when calling refresh().
public class WebCenterGrid {
/*some code here*/
public static final int SEARCH_POPULATE = 286; //integer value doesn't matter
public void refresh(int operation) {
switch(operation) {
case SEARCH_POPULATE: this.searchAndPopulate(); break;
}
/*...some other code here, we don't care..*/
}
Then, at the 'calling' class:
public class AwesomeGridCreator{
//some code here
WebCenterGrid wcg = new WebCenterGrid();
//The parameter that we pass below (2), will make the refresh() method call
//the method that we defined in our switch cases ('searchAndPopulate()').
wcg.refresh(wcg.SEARCH_POPULATE);
}

Which pattern should I use to run some action based on command name?

Prerequisites:
String command = "x";
Data data = request.get();
interface Action {
Response process(Data data);
}
class ActionX implements Action {
public Response process(Data data) {}
}
class Service {
public execute(Action action) {
action.process();
}
}
I dont't understand how to register my actions. The following options are unacceptable:
// bad because too verbose
case "x":
action = new ActionX();
and
// bad because package name is a constant string
action = Class.forName("some.package.name.Action" + command.toUpperCase());
I guess I might try to use Java annotations to solve my problem. Something like this:
#Action(command = "x")
class ActionX implements Action {}
// scan whole classpath etc ...
But maybe I just need to use another pattern....
According to me, Factory design pattern (or Abstract factory design pattern) is suitable in this case. I might be wrong.
Annotation based way is overkill for this situation
Switch case is not verbose at all.
You can try following way with factory pattern,
enum Command {
X("x");
private String commandString;
Command(String commandString) {
this.commandString = commandString;
}
public String getCommandString() {
return commandString;
}
}
interface Action {
void process();
}
class ActionX implements Action {
#Override
public void process() {
System.out.println("Processing..");
}
}
class ActionFactory {
public Action getAction(Command command) {
// Check command and return action
// Switch is the best suitable here
return action;
}
}
Thinking about the situation where you have lots of commands and so many actions.... !? In that case, you must look in to your design first and some sort of more analysis can be done instead of deciding about design patterns first.
Do not use the Class.forName(""). I would go for the switch case but maybe change the command representation to an enum instead of a String.
You can use a map:
Map<String, Action> map = ...;
map.put("x", new ActionX());
Response response = map.get("x").process(data);
It looks like the command name is an inherent part of the command (as opposed to being configured externally). If that's the case, model it that way:
interface Action {
String name();
Response process(Data data);
}
Then you can simply create a Map<String,Action> that uses each action's name as the key.
If you want to make command classes discoverable instead of hard-coding them and you're not using an existing scanner like Spring, you should use the Service Provider Interface.

Linking a String to a Function

Is there a way in Java (Android) to link a string and a function? My aim is to run a certain function depending on what string is received from a seperate method.
ie if myString == "building" then execute buildingmethod();
I was thinking about using a HashMap like so:
HashMap<String,Runnable> hashDBTableUpdateRef = new HashMap<>();
hashDBTableUpdateRef.put("house",this.housemethod());
hashDBTableUpdateRef.put("shed",this.shedmethod());
hashDBTableUpdateRef.put("barn",this.barnmethod());
then
String myString = getCalculatedString();
for (String s : hashDBTableUpdateRef) {
hashDBTableUpdateRed.get(s).run();
}
I can't really make a generic method with a parameter, such as function anyBuilding(String buildingType) due to following actions and custom enumerations. Any thoughts? Is runnable the way forward?
eg:
function housemethod() {
myHouseObject.runSomething();
}
function shedmethod() {
myShedObject.runSomething();
}
function barnmethod() {
myBarnObject.runSomething();
}
Thanks,
you could for example define enum which implements Command interface
interface Command {
void execute();
}
enum MyEnum implements Command {
A() {
public void execute() {
System.out.println("A");
}
},
B {
public void execute() {
System.out.println("B");
}
};
}
now all what you need is convert your string to enum MyEnum.valueOf("someString"); and you returned object you can call execute method.
But still main question remain, why you want to do this and what you want to achieve? because it might be better way.
Your are quite near to get what you want, but you should replace the generic Runnable by a specific interface:
public interface MyInterface
{
public <return-type> doSomething(<parameters>) throws <exceptions>;
}
This is a semantic way to improve your initial design, because you can name your methods, add parameters and exceptions, add more methods, etc.
The rest of your design (a specific implementation for each needed behaviour, and storing them all in a Map) is OK.

Understanding best use of Java Generics in this example case

Let's say I have a manufacturing scheduling system, which is made up of four parts:
There are factories that can manufacture a certain type of product and know if they are busy:
interface Factory<ProductType> {
void buildProduct(ProductType product);
boolean isBusy();
}
There is a set of different products, which (among other things) know in which factory they are built:
interface Product<ActualProductType extends Product<ActualProductType>> {
Factory<ActualProductType> getFactory();
}
Then there is an ordering system that can generate requests for products to be built:
interface OrderSystem {
Product<?> getNextProduct();
}
Finally, there's a dispatcher that grabs the orders and maintains a work-queue for each factory:
class Dispatcher {
Map<Factory<?>, Queue<Product<?>>> workQueues
= new HashMap<Factory<?>, Queue<Product<?>>>();
public void addNextOrder(OrderSystem orderSystem) {
Product<?> nextProduct = orderSystem.getNextProduct();
workQueues.get(nextProduct.getFactory()).add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
factory.buildProduct(workQueues.get(factory).poll());
}
}
Disclaimer: This code is merely an example and has several bugs (check if factory exists as a key in workQueues missing, ...) and is highly non-optimal (could iterate over entryset instead of keyset, ...)
Now the question:
The last line in the Dispatcher (factory.buildProduct(workqueues.get(factory).poll());) throws this compile-error:
The method buildProduct(capture#5-of ?) in the type Factory<capture#5-of ?> is not applicable for the arguments (Product<capture#7-of ?>)
I've been racking my brain over how to fix this in a type-safe way, but my Generics-skills have failed me here...
Changing it to the following, for example, doesn't help either:
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy()) {
Product<?> product = workQueues.get(factory).poll();
product.getFactory().buildProduct(product);
}
}
Even though in this case it should be clear that this is ok...
I guess I could add a "buildMe()" function to every Product that calls factory.buildProduct(this), but I have a hard time believing that this should be my most elegant solution.
Any ideas?
EDIT:
A quick example for an implementation of Product and Factory:
class Widget implements Product<Widget> {
public String color;
#Override
public Factory<Widget> getFactory() {
return WidgetFactory.INSTANCE;
}
}
class WidgetFactory implements Factory<Widget> {
static final INSTANCE = new WidgetFactory();
#Override
public void buildProduct(Widget product) {
// Build the widget of the given color (product.color)
}
#Override
public boolean isBusy() {
return false; // It's really quick to make this widget
}
}
Your code is weird.
Your problem is that you are passing A Product<?> to a method which expects a ProductType which is actually T.
Also I have no idea what Product is as you don't mention its definition in the OP.
You need to pass a Product<?> to work. I don't know where you will get it as I can not understand what you are trying to do with your code
Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
// factory has the type "Factory of ?"
for (Factory<?> factory: workqueues.keySet())
// the queue is of type "Queue of Product of ?"
Queue<Product<?>> q = workqueues.get(factory);
// thus you put a "Product of ?" into a method that expects a "?"
// the compiler can't do anything with that.
factory.buildProduct(q.poll());
}
Got it! Thanks to meriton who answered this version of the question:
How to replace run-time instanceof check with compile-time generics validation
I need to baby-step the compiler through the product.getFactory().buildProduct(product)-part by doing this in a separate generic function. Here are the changes that I needed to make to the code to get it to work (what a mess):
Be more specific about the OrderSystem:
interface OrderSystem {
<ProductType extends Product<ProductType>> ProductType getNextProduct();
}
Define my own, more strongly typed queue to hold the products:
#SuppressWarnings("serial")
class MyQueue<T extends Product<T>> extends LinkedList<T> {};
And finally, changing the Dispatcher to this beast:
class Dispatcher {
Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
#SuppressWarnings("unchecked")
public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
ProductType nextProduct = orderSystem.getNextProduct();
MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
myQueue.add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
buildProduct(workQueues.get(factory).poll());
}
public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
product.getFactory().buildProduct(product);
}
}
Notice all the generic functions, especially the last one. Also notice, that I can NOT inline this function back into my for loop as I did in the original question.
Also note, that the #SuppressWarnings("unchecked") annotation on the addNextOrder() function is needed for the typecast of the queue, not some Product object. Since I only call "add" on this queue, which, after compilation and type-erasure, stores all elements simply as objects, this should not result in any run-time casting exceptions, ever. (Please do correct me if this is wrong!)

Having a Java class where one of the fields is a method?

I'm pretty new to Java, as the nature of my post will give away
I need to create a class which contains a set of methods which can easily be extended by a programmer, should it be needed. I thought about having two classes: Commands and Command. Commands contains an array of Command objects, and is where the programmer can add new commands. The Command class has two fields. The name of the class, and a method signature. I'm not sure how this can be done. In C, I think you can have a struct of functions, so can we have a class where the instances of the class are methods? Or am I completely on the wrong track?
I thought about trying to do something like this:
public class Commands
{
private ArrayList<Command> commands;
/**
* Constructor for objects of class Command
*/
public Commands()
{
createCommands();
}
/**
* This is where a programmer can add new commands
*/
public void createCommands()
{
commands.add(new Command("move", public void move()));
}
/**
* This is where the programmer can define the move command
*/
public void move()
{
....
}
}
public class Command
{
private String command_name;
private Method command;
public Command(String command_name, Method command)
{
this.command_name = command_name;
this.command = command;
}
}
I know there are a lot of things wrong with this, but I'm stuck on finding the right way. Hints/help would be fantastic.
I think you want to use the Command pattern:
In object-oriented programming, the
command pattern is a design pattern in
which an object is used to represent
and encapsulate all the information
needed to call a method at a later
time
The Wikipedia page has an example.
Your Command should be an interface with an execute method. A programmer can code a class that implements the Command interface, and thus she/he must implement the execute method to do what is needed. You can then have a Command[] array, and for each Command object you can simply call execute to perform the task.
Java does not have function pointers. This is a common trick:
abstract class (or interface) Command {
void execute();
}
public void createCommands() {
commands.add(new Command(){
#Override
void execute() {
something.move();
}
});
}
Java doesn't have function pointers, so this doesn't work. What you probably want to do is have a Command interface with an execute() method that you implement in concrete subclasses.
It's a matter of style, but I usually wouldn't have a name field in the Command implementations. Rather, I would just create a Map<String, Command> that holds the name for each Command.
Note that you can't directly pass methods about in Java. Instead, they will need to be objects that implement a common interface. For example, your methods could become objects that implement the Runnable interface. Then you just call "run" when you need to use the method.

Categories

Resources