Multi-Level Enum with Methods in Java - java

I have 2 enums and 2 interfaces that I am trying to create in a specific way. The goal is to form a hierarchy where I can declare a list of methods that belong to one enum and a differnent list of values that belong to the combination of both enums.
For example: the methods declared within LevelOneOperations should belong to LevelOne only. Then methods declared witin LevelTwoOperations should belong to the combination of both together like A.1, A.2, A.3, etc.
public enum LevelOne implements LevelOneOperations {
A {
public boolean isValid(Request obj){ // logic }
public void prepare(Request obj){ // logic }
},
B {
public boolean isValid(Request obj){ // logic }
public void prepare(Request obj){ // logic }
} ...
}
public enum LevelTwo implements LevelTwoOperations {
1 {
public void process(LevelOne lev1, Request obj){
switch(lev1){
case A: // do something
case B: // do something else
case C: // do something else
case D: // do the last thing
}
}
},
2 {
public void process(LevelOne lev1, Request obj){ // logic }
} ...
}
public interface LevelOneOperations {
public boolean isValid(Request obj);
public void prepare(Request obj);
}
public interface LevelTwoOperations {
public void process(LevelOne lev1, Request obj);
}
public class myService {
public void runProcess(Request obj){
LevelOne l1 = LevelOne.valueOf(obj.getLevel1());
LevelTwo l2 = LevelTwo.valueOf(obj.getLevel2());
if(l1.isValid()){
l1.prepare();
l2.process(l1, obj);
}
}
}
Is there a way I can create an enum hierarchy so that I don't need to use switch statements to control the flow of the application. I want to call the process like: LevelOne.LevelTwo.process(obj);
I need methods that apply to LevelOne for all types and some methods that apply to LevelOne.LevelTwo together so that I have a grouped enum like : A.1, A.2, A.3, B.1, B.2, B.3, C.1, C.2, C.3, D.1, D.2, D.3, etc. I am also trying to make it easy to expand upon in the future because these lists are only subsets of what we are expecting for this project.
Tomorrow if I want to add a new LevelOne like E or a new LevelTwo 4 then it shouldn't require a lot of rework to introduce and support a new constant like that. The internal business logic between each element is different. Even between sub levels like: A.1 and A.2 will be different because both enumerators are taken into consideration and effect the output of the process.
The only way that I can think of to implement any thing like this is through switch/case statements. Can you please let me know if there is another way that I can achieve this?
I don't want separate classes for each variation because it will be a lot of different service classes and this is for only one part of my application. Currently I would have 5 elements in my first enumerator and 2 elements in my second enumerator for a total of 10 combinations.

You can use the Visitor pattern for this.
If you add a new enum to either of them, you're forced to implement all the new methods before the code will compile, unlike with a switch where you won't get compilation error if you miss one.
interface VerbAction {
void run();
void walk();
void jump();
}
enum Verb {
Run { #Override void perform(VerbAction action) { action.run(); } },
Walk { #Override void perform(VerbAction action) { action.walk(); } },
Jump { #Override void perform(VerbAction action) { action.jump(); } };
abstract void perform(VerbAction action);
}
enum Noun {
Dog {
#Override
void perform(Verb verb) {
verb.perform(new VerbAction() {
#Override
public void run() {
// Running dog
}
#Override
public void walk() {
// Walking dog
}
#Override
public void jump() {
// Jumping dog
}
});
}
},
Cat {
#Override
void perform(Verb verb) {
verb.perform(new VerbAction() {
#Override
public void run() {
// Running cat
}
#Override
public void walk() {
// Walking cat
}
#Override
public void jump() {
// Jumping cat
}
});
}
},
Pony {
#Override
void perform(Verb verb) {
verb.perform(new VerbAction() {
#Override
public void run() {
// Running pony
}
#Override
public void walk() {
// Walking pony
}
#Override
public void jump() {
// Jumping pony
}
});
}
};
abstract void perform(Verb verb);
}

Related

How Can I Create method In Java With Same Type Parameter?

My code looks like below:
enum EnumType {
CATEGORY,
GROUP,
MAIN
}
Methods:
public void call(EnumType type){
switch(type):
case CATEGORY:
return methodForCategory();
case GROUP:
return methodForGroup();
...
}
public void methodForCategory(){
... Operations according to EnumType.CATEGORY
}
public void methodForGroup(){
... Operations according to EnumType.GROUP
}
public void methodForMain(){
... Operations according to EnumType.MAIN
}
But I want to call it without switch/case like below;
public void call(EnumType type){
methodForType(EnumType type);
}
Is it possible or is there any better alternative?
You can create the method implementation inside the enum as below:
public enum EnumType {
CATEGORY {
#Override
public void processMethod() {
// Do something here
}
},
GROUP {
#Override
public void processMethod() {
// Do something here
}
},
MAIN {
#Override
public void processMethod() {
// Do something here
}
};
public abstract void processMethod();
}
And update call method implementation as:
public void call(EnumType type){
type.processMethod();
}
And switch code should not return anything as method return type is void.
You can use an EnumMap as a registry of methods and using the Enum supplied you can return the correct implementation of the Runnable. I have used Runnable as a functional interface as it takes no inputs and produces no output.
In another class where you have the business logic, you can initialize the map and add the corresponding Runnable implementation:
class Strategy{
private final EnumMap<EnumType, Runnable> map;
public Strategy(){
//Initialize values here
map = new EnumMap<>(EnumType.class);
map.put(EnumType.CATEGORY, () -> {
System.out.println("CATEGORY");
});
map.put(EnumType.GROUP, () -> {
System.out.println("GROUP");
});
map.put(EnumType.MAIN, () -> {
System.out.println("MAIN");
});
}
public void call(EnumType type){
map.get(type).run();
}
}
Then you can invoke the call() method by supplying the type of Enum as a parameter:
public static void main(String args[]){
Strategy str = new Strategy();
str.call(EnumType.CATEGORY);
str.call(EnumType.GROUP);
str.call(EnumType.MAIN);
}

In Java, what is the best way to share functionality between enum value?

I'm considering the best way to create common functionality between enum values, which implement an abstract method declared in the enum.
For example, I want to share the first line of the methods defined by VALUE1 and VALUE2:
public enum EnumExample {
VALUE1() {
public void doSomething(String arg) {
doSomethingElse(); // I don't want to repeat this line
calculateFoo();
},
VALUE2() {
public void doSomething(String arg) {
doSomethingElse(); // I don't want to repeat this line
calculateBar();
}
},
VALUE3() {
public void doSomething(String arg) {
doSomethingUnrelated(); // This value DOES NOT share functionality with VALUE1 & VALUE2
}
};
public abstract void doSomething(String arg);
}
Currently, I just repeat the code for each value, but I'm sure there is a better way.
Any help will be much appreciated!
I'm not sure whether this is any better for you, but I like lambdas for this sort of situation. I make the enum implement a Functional Interface, then each value can delegate to its own private implementation.
import java.util.function.Consumer;
public enum EnumExample implements Consumer<String> {
VALUE1(t -> {
doSomethingElse();
calculateFoo();
}),
VALUE2(t -> {
doSomethingElse();
calculateFoo();
}),
VALUE3(t -> doSomethingUnrelated());
private final Consumer<String> myLambda;
EnumExample(Consumer<String> aLambda) {
myLambda = aLambda;
}
static void doSomethingElse() {}
static void calculateFoo() {}
static void doSomethingUnrelated() {}
#Override
public void accept(String t) {
myLambda.accept(t);
}
}
It still repeats your method calls, but it looks cleaner to my eyes.
You can implement the "generic" operation on the "base enum class" and define the specific operation as abstract, so it must be implemented:
enum EnumExample {
VALUE1 {
#Override
void doSomethingSpecific() {
System.out.println("specific for " + VALUE1);
}
},
VALUE2 {
#Override
void doSomethingSpecific() {
System.out.println("specific for" + VALUE2);
}
};
public void doSomething(){
doSomethingGeneric();
doSomethingSpecific();
}
void doSomethingGeneric(){
System.out.println("Same for all enums...");
};
abstract void doSomethingSpecific();
}

Sad logic on types

Code base is littered with code like this:
BaseRecord record = // some BaseRecord
switch(record.source()) {
case FOO:
return process((FooRecord)record);
case BAR:
return process((BarRecord)record);
case QUUX:
return process((QuuxRecord)record);
.
. // ~25 more cases
.
}
and then
private SomeClass process(BarRecord record) { }
private SomeClass process(FooRecord record) { }
private SomeClass process(QuuxRecord record) { }
It makes me terribly sad. Then, every time a new class is derived from BaseRecord, we have to chase all over our code base updating these case statements and adding new process methods. This kind of logic is repeated everywhere, I think too many to add a method for each and override in the classes. How can I improve this?
First solution: good old polymorphism.
Simply add an abstract process() method to the BaseRecord class, and override it in every subclass. The code will thus become:
BaseRecord record = ...;
record.process();
If you can't add the process() method into the BaseRecord class (and its subclasses), then implement the visitor pattern. It will leave the process method outside of the BaseRecord class, but each time you add a new subclass, you'll be forced to modify the Visitor interface, and all its implementations. The compiler will thus check for you that you haven't forgotten a case somwhere in a switch.
public interface RecordVisitor<T> {
T visitFoo(FooRecord foo);
T visitBar(BarRecord foo);
...
}
public abstract class BaseRecord {
public abstract <T> T accept(RecordVisitor<T> visitor);
}
public class FooRecord extends BaseRecord {
#Override
public <T> T accept(RecordVisitor<T> visitor) {
return visitor.visitFoo(this);
}
}
public class BarRecord extends BaseRecord {
#Override
public <T> T accept(RecordVisitor<T> visitor) {
return visitor.visitBar(this);
}
}
Now you simply have to implement RecordVisitor for each block of logic described in the question:
RecordVisitor<Void> visitor = new ProcessRecordVisitor();
record.accept(visitor);
Both Visitor Pattern and Strategy pattern can be put in use here. http://en.wikipedia.org/wiki/Strategy_pattern and http://en.wikipedia.org/wiki/Visitor_pattern
I think this is instructive:
package classplay;
public class ClassPlay
{
public void say(String msg) { System.out.println(msg); }
public static void main(String[] args)
{
ClassPlay cp = new ClassPlay();
cp.go();
}
public void go()
{
A someClass = new C();
say("calling process with double dispatch");
someClass.dueProcess(this);
say("now calling process directly");
process(someClass);
}
public void process(A a)
{
say("processing A");
a.id();
}
public void process(B b)
{
say("processing B");
b.id();
}
public void process(C c)
{
say("processing C");
c.id();
}
abstract class A
{
abstract public void id(); // { System.out.println("Class A"); }
public void dueProcess(ClassPlay cp) { cp.process(this); }
}
class B extends A
{
public void id() { System.out.println("Class B"); }
public void dueProcess(ClassPlay cp) { cp.process(this); }
}
class C extends A
{
public void id() { System.out.println("class C"); }
public void dueProcess(ClassPlay cp) { cp.process(this); }
}
}

Blackberry design pattern question:

I'm implementing a class that is responsible for all my HTTP requests from the Blackberry. I have around 10 or so screens that use this class to query a web service and get data from it. What would be the standard pattern to use in this case?
Currently I have it setup as follows -
public class NetworkAccessClass
{
public NetworkAccessClass(String url, String methodName, Vector paramNames, Vector paramValues, MainScreen screen) {
// perform inits
}
public void run() {
// Get Data
if(screen.instanceOf(LoginScreen)) {
((LoginScreen) screen).requestSucceded(responseData);
}
// So on for all 10 screens.
catch() {
((LoginScreen) screen).requestFailed(errorCode);
// So on for all 10 screens.
}
}
}
It works, but doesn't look right, and if a single screen has multiple types network requests, I'm being forced to add a flag to keep track of which function it's supposed to call back.
Is there a better way to do this?
Thanks,
Teja.
Use a callback interface, e.g. ResponseHandler:
public class NetworkAccessClass
{
public interface ResponseHandler {
void requestSucceeded(ResponseData responseData);
void requestFailed(ErrorCode errorCode);
}
public NetworkAccessClass(
String url,
String methodName,
Vector paramNames,
Vector paramValues,
ResponseHandler responseHandler) {
// perform inits
}
public void run() {
// Get Data
try {
...
responseHandler.requestSuceeded(responseData);
catch() {
responseHandler.requestFailed(errorCode);
}
}
}
This hopefully decouples your NetworkAccessClass from knowing about all the screens. Then either your screens implement NetworkAccessClass.ResponseHandler or they pass an adapter handler (anonymous inner class) to call the proper methods on the screen, e.g.
class LoginScreen {
...
new NetworkAccessClass(url, methodName, paramNames, paramValues,
new ResponseHandler() {
#Override
void requestSucceeded(ResponseData responseData) {
LoginScreen.this.handleLoginSuccess(responseData);
}
#Override
void requestFailed(ErrorCode errorCode) {
LoginScreen.this.handleLoginFailure(errorCode);
}
}
...
}
You could use a listener, which is a simple interface the network class would call back whenever something interesting happens :
public interface NetworkListener {
void requestSucceeded(byte[] responseData);
void requestFailed(int errorCode);
}
public class NetworkAccess {
// ...
public void run() {
// Get Data
if (successful) {
fireSucess(responseData);
}
catch(SomeException e) {
fireFailure(errorCode);
}
}
public void addNetworkListener(NetworkListener listener) {
// add listener to list of listeners
}
private void fireSuccess(byte[] responseData) {
for (NetworkListener l : listeners) {
l.requestSucceeded(responseData);
}
}
// ...
}
public class LoginScreen {
private void foo() {
NetworkAccess access = new NetworkAccess(...);
access.addNetworkListener(new NetworkListener() {
public void requestSucceeded(byte[] responseData) {
// do what you want
}
public void requestFailed(int errorCode) {
// do what you want
}
});
}
}
This is known as the Observable/observer pattern. The observable notifies its observers when something happens, but without having to know their exact type. The listsner class decouples the two parties.

Can IntelliJ automatically create a decorator class?

Sometimes, I create a decorator class like this:
class MyInterfaceDecorator implements MyInterface {
private final MyInterface delegate;
... constructor taking a MyInterface instance ...
#Override
public Object someInterfaceMethod(Some argument) {
return delegate.someInterfaceMethod(argument);
}
... etc, more methods here...
}
Can IntelliJ automatically create this class for me?
Update//
I noticed that IntelliJ has a "Generate" option for generating delegate methods. Create a new class:
public class MyDecoratorClass {
private MyInterfaceWithManyMethods myInterface;
}
Then mark myInterface, go to Menu > Code > Delegate Methods, select all methods you want to wrap and that's it.
//End of update
You could try the "Refactoring" -> "Replace inheritance with delegation" refactoring. It should be able to do this, like this. I call this "Code with Alt+Enter"
Go to the interface you want to generate a decorator for.
public interface MyInterfaceWithManyMethods {
void method1();
void method2();
void method3();
}
Press Alt+Enter, select "Implement Interface", give a name to your Decorator like "MyDecorator". This gives you
public class MyDecorator implements MyInterfaceWithManyMethods {
public void method1() {
}
public void method2() {
}
public void method3() {
}
}
In new class, select the class name, then "Refactor" -> "Replace inheritance with delegation", select your interface, tick all method names, press enter. You'll get:
public class MyDecorator {
private final MyObject object = new MyObject();
public void method1() {
object.method1();
}
public void method2() {
object.method2();
}
public void method3() {
object.method3();
}
private class MyObject implements MyInterfaceWithManyMethods {
public void method1() {
}
public void method2() {
}
public void method3() {
}
}
}
Delete the inner class and the object initializer manually. You get:
public class MyDecorator {
public void method1() {
object.method1();
}
public void method2() {
object.method2();
}
public void method3() {
object.method3();
}
}
Press Alt+Enter on the "object" which is now marked red, select "Create field", select MyInterfaceWithManyMethods.
public class MyDecorator {
private MyInterfaceWithManyMethods object;
public void method1() {
object.method1();
}
public void method2() {
object.method2();
}
public void method3() {
object.method3();
}
}
Select the object variable, press Alt+Enter, select "Add constructor Parameter":
public class MyDecorator {
private MyInterfaceWithManyMethods object;
public MyDecorator(MyInterfaceWithManyMethods object) {
this.object = object;
}
public void method1() {
object.method1();
}
public void method2() {
object.method2();
}
public void method3() {
object.method3();
}
}
You see it's all done with a few strokes of Alt+Enter. Reads like a lot of work but it can be done in less than 20 seconds. If you just have like 2 or 3 methods you might be faster with a live template, however if you have many methods with complex signatures you'll get a working result in about 20 seconds with this method. Alt+Enter simply rocks :D
You can perhaps add a file template like:
class ${NAME} implements ${INTERFACE} {
private final ${INTERFACE} delegate;
public ${NAME}(final ${INTERFACE} delegate) {
this.delegate = delegate;
}
and then when you have created the file using this template, just use
Alt+Inser and choice delegate Methods.
It's not perfect, but this could be a shortcut

Categories

Resources