I have the following code:
enum Example {
ex1,ex2
}
public void method(Example exType) {
if(exType.equals(ex1)) {
//do similar stuff
method2(exType)
} else if(exType.equals(ex2)) {
//do similar stuff
method2(exType)
} else {
//throw exception
}
}
public void method2(Example exType) {
if(exType.equal(ex1)) {
//do similar stuff
} else if(exType.equals(ex2)) {
//do similar stuff
} else {
//throw exception
}
}
The problem is the method calls other methods that behave in the same way. So it doesn't look very good as an implementation. How can i split this behavior?
Edit:
Using enum is not mandatory. Similar means they call same-named method and update same-named fields, one just does less than the other. Inside the //Do similar stuff it calls another method with the enum as a parameter and that method has the same structure of code.
Edit 2:
Added some more code. This just doesn't seem like the right approach
It's worth remembering that Enum values are objects rather than int values like they are in other languages. This allows you to use polymorphism with them removing the need for switch statements in many cases.
interface IExample {
// you can use interfaces if you need them
void method1();
}
enum Example implements IExample {
ex1 {
public void method1() {
// do stuff
method2();
}
public void method2() {
// do other stuff
}
},
ex2 {
public void method1() {
// do stuff
method2();
}
public void method2() {
// do other stuff
method3(); // not all methods need to be different.
}
};
public abstract void method1(); // only needed if you don't use an interface
public abstract void method2(); // does it need to be public as well?
public void method3() { /* added as an example */ }
}
There is no need to throw an exception as your code won't compile if you forget to provide an implementation for a new enum value.
The IExample might be an existing interface or it might be needed for extention. e.g.
class Example2 implements IExample {
int x;
public Example2(int x) { this.x = x; }
public void method1() {
// uses x
}
}
Now you can write
IExample e = Example.ex1; // fixed value
IExample e2 = new Example2(5); // extendable at runtime.
Why would you do this?
There is an example I use.
SystemTimeProvider - a singleton implemented as an enum
SetTimeProvider a class where each instance can have a different fixed time for testing purposes.
I would use a switch instead. Also with Enums you can use ==, but you don't need that when using a switch. What about this!
enum Example {
ex1,ex2
}
public void method(Example exType) {
switch (exType) {
case ex1:
// do 1
break;
case ex2:
// do 2
break;
default:
//throw exception
}
}
First of all its better to use switch case because in case in future there are more no of enums and then more no of if conditions then code becomes less readable.
One of the approach could be
enum Example {
ex1,ex2
}
public void method(Example exType) {
switch (exType) {
case ex1:
methodEx1();
break;
case ex2:
methodEx1();
break;
default:
//throw exception
}
}
Function methodEx1(); and methodEx2(); add all the codes corresponds to enum in a single function instead of writing of multiple function for same enum.
Related
I have method which returns sql query as string. This method consider parameter 'level' , based on this
parameter there are multiple if else statement like
if(level.equals("A1")){
// add some field in query
}
else if (level.equals("A2"))
{
// add some field and logic in query
}
..
so on
In future number of levels are going to increase and I don`t want to write pesky if else statements so I am looking for cleaner and maintainable design approach for this scenario.
I am thinking of strategy design pattern but not sure whether it is best for this scenario.
You have several options:
if/else if as you've indicated.
A switch statement.
A Map with the keys being the level string and the values being references of a functional interface type (Runnable or an appropriate interface from java.util.function, or your own) you can initialize with method references, lambdas, anonymous class instances, or even concrete class instances as required.
Here's an example of that last option, using the most basic functional interface, Runnable, with method references:
import java.util.Map;
import java.util.HashMap;
public class Example {
private Map<String, Runnable> handlers;
public Example() {
this.handlers = new HashMap<String, Runnable>();
this.handlers.put("A1", this::a1action);
this.handlers.put("A2", this::a2action);
}
private void a1action() {
System.out.println("Action A1");
}
private void a2action() {
System.out.println("Action A2");
}
public void handleAction(String action) {
Runnable handler = this.handlers.get(action);
if (handler == null) {
System.out.println("No handler for '" + action + "'");
} else {
handler.run();
}
}
public static void main(String[] args) throws Exception {
Example ex = new Example();
ex.handleAction("A1");
ex.handleAction("A2");
ex.handleAction("A3");
}
}
You can use an enum to list the operations and use valueOf to work out which to use.
enum Levels {
A1 {
#Override
void doSomethingToTheQuery(Query q) {
// add some field in query
}
},
A2{
#Override
void doSomethingToTheQuery(Query q) {
// add some field and logic in query
}
};
abstract void doSomethingToTheQuery(Query q);
}
public void test() {
// Lookup the level and do hack the query.
Levels.valueOf("A1").doSomethingToTheQuery(q);
}
You can then add new levels just by adding to the enum.
My question is not Java specific but I think it's more like a design-patterns question.
I'll try to explain with an example :
I have two classes (A and B), B is extending A.
The two classes look like this :
public class A {
protected int method1() {
System.out.println(method3());
}
protected int method3() {
return 3;
}
}
.
public class B extends A {
protected void method2() {
//Calling method1
method1(); // Output : 3
//Calling method1 another time but method3 needs to be slightly different
method1(); // Output needs to be : 6
}
}
So, I'd like to call two times the same method but I want to modify what is inside method3() when calling it the second time.
Obviously I don't want to define two different method1() because method1 is not only printing out an int but it is doing more.
The second method3 could look like this :
protected int method3bis() {
return 2*3;
}
I'd really like to avoid passing some kind of argument through all the methods, something which would look like this :
protected int method1(int arg) {
if(arg == 0)
System.out.println(method3());
if(arg == 1)
System.out.println(method3bis());
}
Do you know any good way to do this ?
Thanks in advance :-)
There is no way to change the implementation of a method at run time in Java.
When you override a method, it is possible to call the direct superclass implementation, for example:
class Super {
void method1() {
System.out.println(3);
}
}
class Sub {
#Override
void method1() {
System.out.println(2 * 3);
}
void method2() {
// printing 3
super.method1();
// printing 6
this.method1();
}
}
However, this cannot be used in the way you have described (calling method1 while changing the implementation of method3). And it would also be a very disorganized way to implement what you have described.
You should use method parameters because this is what they are for.
You can accomplish this with reflection by creating a new A object, but this is not a good way to go about it. You're better off using if/else blocks.
import java.lang.reflect.*;
public class B extends A {
protected void method2() {
try {
Class a = Class.forName("A");
Object aa = a.newInstance();
((A) aa).method1(); // Output : 3
} catch (Exception e) {
e.printStackTrace();
}
//Calling method1 another time but method3 needs to be slightly different
this.method1(); // Output needs to be : 6
}
#Override
protected int method3() {
return 2*3;
}
}
I want to make an if statement that checks to see which method made the call to a secondary method.
I will write what i want in pseudo code so you can see what I mean.
public static void methodOne() {
methodToCall();
}
public static void methodTwo() {
methodToCall();
}
public static void methodThree() {
methodToCall();
}
public static void methodToCall() {
if (methodOne made the call == true) {
execute this
} else if (methodTwo made the call == true){
execute this
} else if (methodThree made the call == true){
execute this
} else {
System.out.println("How did you get here?");
}
}
That's about the gist of it. I want a simple check to see which method made the call so I can choose which operation is relevant to the call.
Is this possible?
If it is not possible, is there a work around?
This is called 'state orientation', and it was debated extensively in the 1970s, possibly even the 1960s. The conclusion was that if you need to know this sort of thing you are already doing something seriously wrong, by introducing a two-way dependency into the code. What happens for example when you add another caller?
Use three short methods, instead of combining the logic of three short methods into one larger method. Once the short methods are created Just call the appropriate method from each calling method.
public static void methodOne() {
methodToCall1();
}
public static void methodTwo() {
methodToCall2();
}
public static void methodThree() {
methodToCall3();
}
public static void methodToCall1() {
int x = 0;
x = x - 3; //some custom logic to prep argument
commonLogic(x);
}
public static void methodToCall2() {
//Method 2 logic
int x = 0;
x = x + 3; //some custom logic to prep argument
commonLogic(x);
}
public static void methodToCall3() {
//Method 3 logic
int x = 0;
x = x * 3; //some custom logic to prep argument
commonLogic(x);
}
public static void commonLogic(int arg1){
//peform common logic
}
If these three methods would contain duplicate code, abstract the duplicate code into another method then call that method from within each of the smaller methods. The idea is to prepare the arguments to call the common function in each of the three smaller functions, then call the common function with those arguments.
A great deal of the abstraction afforded by methods comes from the fact that they do not need to know who is calling them, so the answer to your question is "no". It does not mean that you cannot make it work, though: make the callers pass some sort of a token (say, an enum value) identifying themselves to the callee. This would let you dispatch on that identity inside your method's implementation:
enum CallerContext {CALLER1, CALLER2, CALLER3};
...
public static void methodToCall(CallerContext context) {
...
}
This is not the most Object-Oriented way of doing things, however: very often, a better approach would be letting the callers supply the logic to be executed, rather than supplying a token identifies that logic. See Visitor Pattern for details on that approach.
You can do it by examining the call stack via Thread.getStackTrace():
public static void methodToCall(Action action) {
String callingMethod = Thread.currentThread().getStackTrace()[2].getMethodName();
if (callingMethod.equals("methodOne")) {
execute this0
} else if (callingMethod.equals("methodTwo")) {
execute this
} else if (callingMethod.equals("methodThree")) {
execute this
} else {
System.out.println("How did you get here?");
}
}
but you shouldn't - it's a bit anti-OO. Instead, change your method signature to something like this:
public enum Action {ONE, TWO, THREE}
public static void methodToCall(Action action) {
if (action == ONE) {
execute this
} else if (action == TWO) {
execute this
} else if (action == THREE) {
execute this
} else {
System.out.println("How did you get here?");
}
}
If you end up using an enum, then make sure to take advantage of the fact that enums in Java are no less than singleton instances of classes. Therefore you can declare the method as abstract in the enum definition and then override it in each instance, instead of passing the enum as a paramater to some method defined outside of the enum's context.
So it would look something like:
enum Method {
Mode1 {
#Override
void call() {
// do stuff
}
}, Mode2 {
#Override
void call() {
// do stuff differently
}
}, Mode3 {
#Override
void call() {
// do stuff even more differently
}
};
abstract void call();
}
And then you either don't need your wrapping methods, or, if they were supposed to do anything more, you write:
public static void methodOne() {
// some code
Method.Mode1.call();
// some code
}
There is a recurring pattern when I have for example an enum or a String and I want to dispatch based on the value of that parameter:
public void myMethod(String parameter) {
if(parameter.equals(something)) {
doSomething();
} else if(parameter.equals(somethingElse)) {
doSomethingElse();
}
}
What is the idiomatic way to get rid of the lengthy if or case statements? I'm thinking about something like the single dispatch generic functions in python but I want to dispatch based on value not on type.
#fun.register(int)
def _(arg, verbose=False):
if verbose:
print("Strength in numbers, eh?", end=" ")
print(arg)
#fun.register(list)
def _(arg, verbose=False):
if verbose:
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, elem)
I find that this is most common when dealing with forms (as an example) that have multiple "actions". Although this may seem overkill, a lot of times it's actually much cleaner (and in many ways, easier) to simply "register" action handlers.
public class Dispatcher {
private Map<String, ActionHandler> actionHandlerMap = new HashMap<String, ActionHandler>();
public void perform(String action) {
ActionHandler handler = actionHandlerMap.get(action);
if (null == handler) {
// no handler - throw an exception?
}
handler.execute();
}
public void addActionHandler(ActionHandler handler) {
actionHandlerMap.put(handler.getAction(), handler);
}
}
public interface ActionHandler {
public String getAction();
public void execute();
}
It is absolutely more code, but it's extensible, clean, and allows for a better separation of concerns. It's also much more easily testable which is always a good thing.
you could use method overriding in java.. so the equivalent should be something like
public void doSomething(String arg) {
//do something when param is string
}
public void doSomething(List<String> arg) {
//do something else when param is a List of String
}
In Java enum is a class as well, so you could extextend it and use it as :
interface Doable {
void doSomething();
}
enum Stuff implements Doable {
ONE() {
public doSomething() { System.out.println("do one");};
},
TWO() {
public doSomething() { System.out.println("do two");};
}
}
Doable s = Stuff.valueOf("ONE");
s.doSomething();
I have a Java method with a switch statement.
It’s working fine, but I have a lot of cases, perhaps 20 or more, as shown below.
switch (result) // result is of type Enum
{
case 1:
break;
case 2:
break;
//----
//----
//----
default:
break;
} // End of Switch
Please let me know how to shift these cases into another file.
No, Java does not have an #include facility like C does.
You're better off simply refactoring your logic. The fact that you're asking at all tells me you may well need some better abstractions.
But, at a minimum you could do:
public class HandleCases {
public static Result handleCase1(...parameters...) {
...
}
public static Result handleCase2(...parameters...) {
...
}
public static Result handleCase3(...parameters...) {
...
}
}
and then:
Result r = null;
switch(flag) {
case 1:
r = HandleCases.handleCase1( ... );
break;
case 2:
r = HandleCases.handleCase1( ... );
break;
case 3:
r = HandleCases.handleCase1( ... );
break;
...
}
The Result holder is where you can get back any values you need.
But overall this is a patchwork, your design could probably use some work.
if the switch condition is an actual enum, you can implement a method on the enum, e.g.
public enum Colors {
RED { public void run() { /* do stuff for red */ } },
GREEN { public void run() { /* do stuff for green */ } },
BLUE { public void run() { /* do stuff for blue */ } },
public abstract void run();
}
your switch would then be a method call:
Color result = ...;
// was switch (result) { case RED: ... }
result.run();
The result is the "switch" is in a separate file. Enums make it easy, but still have all the "switch" code in one file, just now the enum's file. You could follow the same pattern, defining each constant in its own singleton class, and all implement the same interface/abstract class, to get each condition in a separate file.
If you have lots of switches that do different things with the same constants, another option to explore is the visitor pattern. http://en.wikipedia.org/wiki/Visitor_pattern
You can't do that. What you can do, however, is that if you have multiple case statements for the same condition, then you can group them together. This is called Fall Through.
switch(flag) {
case 1:
case 3:
case 5:
System.out.println("Odd");
break;
case 2:
case 4:
case 6:
System.out.println("Even");
break;
}
For an immediate solution without redesign, you can use Will's solution. But as he already pointed out, it seems you should do a redesign.
For this, consider the following code example from http://c2.com/cgi/wiki?SwitchStatementsSmell, which uses dynamic dispatch instead of a manual switch statement:
method foo(int thingType) {
switch (thingType) {
case TYPE_ONE:
oneFoo();
break;
case TYPE_TWO:
twoFoo();
break;
case TYPE_THREE:
threeFoo();
break;
case TYPE_FOUR:
fourFoo();
break;
}
}
method oneFoo() {
}
method twoFoo() {
}
method threeFoo() {
}
method fourFoo() {
}
method bar(int thingType) {
switch (thingType) {
case TYPE_ONE:
oneBar();
break;
case TYPE_TWO:
twoBar();
break;
case TYPE_THREE:
threeBar();
break;
case TYPE_FOUR:
fourBar();
break;
}
}
method oneBar() {
}
method twoBar() {
}
method threeBar() {
}
method fourBar() {
}
versus
class one extends base {
method foo() {
}
method bar() {
}
}
class two extends base {
method foo() {
}
method bar() {
}
}
class three extends base {
method foo() {
}
method bar() {
}
}
class four extends base {
method foo() {
}
method bar() {
}
}
Then you can simply call anObjectOfTypeBase.foo() and anObjectOfTypeBase.bar().
It depends on how you want to do it.
First, if the logic is related to the same class (and it is tightly coupled), then no, you can't just shift it out to another one. However, if you want to separate the logic from this class to another one, then it's possible to create a static method in another class to just perform the switch statement.
Alternatively, you can revisit and refactor your code such that a switch statement of 20 isn't necessary.
No, you can't. In Java the entire code of the same class has to be on the same file, even more the code of the same method or statement.
What you can do, if you have many cases is too trasform your "switch" approach in an HashMap approach.
You can create for example an abstract Action class, and put in the Map many actions, that are different classes on different files.
Then in your code you can do something like this:
Action action = map.get(result);
if (action != null)
action.execute();
else
// default case
This pattern is called Command Pattern.