I am making a multiplayer game which makes heavy use of a serialisable Event class to send messages over a network. I want to be able to reconstruct the appropriate subclass of Event based on a constant.
So far I have opted for the following solution:
public class EventFactory {
public static Event getEvent(int eventId, ByteBuffer buf) {
switch (eventId){
case Event.ID_A:
return EventA.deserialise(buf);
case Event.ID_B:
return EventB.deserialise(buf);
case Event.ID_C:
return EventC.deserialise(buf);
default:
// Unknown Event ID
return null;
}
}
}
However, this strikes me as being very verbose and involves adding a new 'case' statement every time I create a new Event type.
I am aware of 2 other ways of accomplishing this, but neither seems better*:
Create a mapping of constants -> Event subclasses, and use clazz.newInstance() to instantiate them (using an empty constructor), followed by clazz.initialiase(buf) to supply the necessary parameters.
Create a mapping of constants -> Event subclasses, and use reflection to find and call the right method in the appropriate class.
Is there a better approach than the one I am using? Am I perhaps unwise to disregard the alternatives mentioned above?
*NOTE: in this case better means simpler / cleaner but without compromising too much on speed.
You can just use a HashMap<Integer,Event> to get the correct Event for the eventID. Adding or removing events is going to be easy, and as the code grows this is easy to maintain when compared to switch case solution and speed wise also this should be faster than switch case solution.
static
{
HashMap<Integer,Event> eventHandlerMap = new HashMap<>();
eventHandlerMap.put(eventId_A, new EventHandlerA());
eventHandlerMap.put(eventId_B, new EventHandlerB());
............
}
Instead of your switch statement Now you can just use :
Event event = eventHandlerMap.get(eventId);
if(event!=null){
event.deserialise(buf);
}
If you're not afraid of reflection, you could use:
private static final Map<Integer, Method> EVENTID_METHOD_MAP = new LinkedHashMap<>();
static {
try {
for (Field field : Event.class.getFields())
if (field.getName().startsWith("ID_")) {
String classSuffix = field.getName().substring(3);
Class<?> cls = Class.forName("Event" + classSuffix);
Method method = cls.getMethod("deserialize", ByteBuffer.class);
EVENTID_METHOD_MAP.put(field.getInt(null), method);
}
} catch (IllegalAccessException|ClassNotFoundException|NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
public static Event getEvent(int eventId, ByteBuffer buf)
throws InvocationTargetException, IllegalAccessException {
return (Event) EVENTID_METHOD_MAP.get(eventId).invoke(null, buf);
}
This solution requires that int ID_N always maps to class EventN, where N can be any String where all characters return true for the method java.lang.Character.isJavaIdentifierPart(c). Also, class EventN must define a static method called deserialize with one ByteBuffer argument that returns an Event.
You could also check if field is static before trying to get its field value. I just forget how to do that at the moment.
Related
I have a java class with 3 boolean property like this
boolean isActive;
boolean isEnable;
boolean isNew;
every property is related to an enum (e.g. ACTIVE,ENABLE,NEW).
I want to have 2 lists of enum. One which has only the enums related to true property value and one for the false one.
just to be clear. using if-else statement I could have
Set<FlagEnum> flagSet = new HashSet<>();
Set<FlagEnum> falseFlagSet = new HashSet<>();
if (object.isActive()) {
flagSet.add(ACTIVE);
} else {
falseFlagSet.add(ACTIVE);
}
if (object.isEnable()) {
flagSet.add(ENABLE);
} else {
falseFlagSet.add(ENABLE);
}
if (object.isNew()) {
flagSet.add(NEW);
} else {
falseFlagSet.add(NEW);
}
is there a way to avoid all these if-else?
I tried with something like
Map<boolean, List<Pair<boolean, FlagEnum>>> res = Stream.of(
new Pair<>(object.isActive(), ACTIVE),
new Pair<>(object.isNew(), NEW),
new Pair<>(object.isEnable(), ENABLE))
.collect(Collectors.partitioningBy(Pair::getKey));
but the resulted structure is an additional complexity which I would like to avoid.
In my real case, I have more than 15 boolean properties...
You can simplify this in various ways. Which of them make sense, depends on your exact requirements.
You can derive the falseFlagSet trivially from the flagSet using EnumSet.complementOf after populating the flagSet:
EnumSet<FlagEnum> falseFlagSet = EnumSet.complementOf(flagSet);
This assumes that all FlagEnum values have corresponding flags. If that's not the case then you need to construct a EnumSet with all enums that have flags and subtract flagSet from that using removeAll.
#1 already removes the need for the else in your cascade, simplifying the code to
if (object.isActive()) {
flagSet.add(ACTIVE);
}
if (object.isEnable()) {
flagSet.add(ENABLE);
}
if (object.isNew()) {
flagSet.add(NEW);
}
If you have enough different flags, then you can create a mapping from getter method to FlagEnum value like this:
Map<Function<YourClass,Boolean>,FlagEnum> GETTERS = Map.of(
YourClass::isActive, FlagEnum.ACTIVE,
YourClass::isNew, FlagEnum.NEW,
YourClass::isEnable, FlagEnum.ENABLE);
Then you can use this to make the whole process data-driven:
EnumSet<FlagEnum> getFlagSet(YourClass yourObject) {
EnumSet<FlagEnum> result = EnumSet.noneOf(FlagEnum.class);
for (Map.Entry<Function<YourClass,Boolean>, FlagEnum> getter : GETTERS.entrySet()) {
if (getter.getKey().apply(yourObject)) {
result.add(getter.getValue());
}
}
return result;
}
If the number of flags is very big, then you could switch entirely to reflection and detect the flags and matching getters dynamically using string comparison, but I would not suggest that approach. If you need something like that then you probably should switch to a framework that supports that kind of feature and not implement it yourself.
That last two obviously only makes sense when the number of flags is big. If it's actually just 3 flags, then I wouldn't mind and just have 3 simple if statements.
As a slight tangent: GETTERS above should definitely be an immutable map (wrap it in Collections.unmodifiableMap or use something like Guava ImmutableMap) and it could be argued that the same applies to the return value of the getFlagSet method. I've left those out for succinctness.
You can use a private helper method for this.
private void addFlagSet(boolean condition, FlagEnum flagEnum,
Set<FlagEnum> flagSet, Set<FlagEnum> falseFlagSet) {
Set<FlagEnum> chosenFlagSet = condition ? flagSet: falseFlagSet;
chosenFlagSet.add(flagEnum);
}
Call it as:
addFlagSet(object.isActive(), FlagEnum.ACIVE, flagSet, falseFlagSet);
addFlagSet(object.isNew(), FlagEnum.NEW, flagSet, falseFlagSet);
addFlagSet(object.isEnable(), FlagEnum.ENABLE, flagSet, falseFlagSet);
You could probably use Reflection to get all methods, then check if a getReturnType() == boolean.class. Problem is the connection between the method's name and the enum. If every single one is named like the method without the 'is', you could use FlagEnum.valueOf() to retrieve the enum value from the method name and use it.
I think this could be the easiest and clearest way to do what I need
Map<Boolean, Set<FlagEnum>> flagMap = new HashMap<>();
flagMap.computeIfAbsent(object.isActive(), h -> new HashSet()).add(ACTIVE);
flagMap.computeIfAbsent(object.isEnabled(), h -> new HashSet()).add(ENABLE);
flagMap.computeIfAbsent(object.isNew(), h -> new HashSet()).add(NEW);
//to get TRUE set simply :
flagMap.get(true);
what do you think?
I love Optional in Java. It has, in one simple class, allowed me to clearly identify return types and arguments which may or may not be available.
One thing that I struggle with is the necessity of assigning it to a short-lived variable which is then inherited into every subsequent scope.
I like to use the simple variable name opt when using optionals like this:
Optional<ThingA> opt = maybeGetThing();
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
...
But when I then need a variable name to use in this scope...
void method() {
Optional<ThingA> opt = maybeGetThing();
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// Duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
}
}
I can use things like optA and optB and so on. But I wonder if there is another way to write this code without having to enumerate my temporary variables. This just smacks of lazy variable names like a aaaa aaaaaabbb or something.
I don't want to name all of my optionals explicitly like this:
Optional<ThingA> optUsefulVariableName = maybeGetThing();
if (optUsefulVariableName.isPresent()) {
ThingA usefulVariableName = optUsefulVariableName.get();
...
While accurate, it is extremely verbose. I also try to use throwaway names like opt and i to indicate that these are in fact only temporary and should serve no purpose beyond their immediate scope (even though they will be inherited).
UPDATE:
I have seen suggestions for using ifPresent() but I don't see how I can use this for instances where I also need to perform an action if the optional is empty:
void method() {
Optional<ThingA> opt = maybeGetThing();
if (!opt.isPresent()) {
doSomethingOnlyHere();
return;
}
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// Duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
}
}
When I try to refactor with ifPresent():
void method() {
// Doesn't handle instance where I need side effects on an empty optional
maybeGetThing().ifPresent(usefulVariableName -> {
...
}
}
The most basic way to eliminate the variable and the need to call Optional#get is to use Optional.ifPresent which calls a function if the Optional has a value.
maybeGetThing().ifPresent(val -> {
// do stuff with side effects here
});
This is still quite a limited way to use Optional, as one of Optionals key purposes is to facilitate programming in a functional style. If you are a beginner this may be a little lost on you, but the idea is to have functions that return something and not functions that rely on side effects. Functions relying on side effects cannot be chained together and are generally harder to reason about.
Technically Optional is something called a Functor (from category theory). It is a wrapper around a value (Whatever T is) and it allows the value to be passed through a series of operations to operate on it and pass it to the next operation until we have what we want, then the chain of operations ends with a terminal (i.e. final) operation. The terminal operation may return the unwrapped value if it exists or it could throw or return some default value if it doesn't.
For Optional it will skip any subsequent operations if the value becomes not present.
There are common operations like map, filter, flatMap (ok that's a Monad operation) and other more java specific operations like Optional#orElse and Optional#orElseThrow.
To refactor your example code you could do this.
void method() {
return maybeGetThing().flatMap(val -> {
// eek side effects
val.doA();
val.doB();
val.doC();
return val.maybeAnotherThing();
});
}
flatMap is a way of converting an Optional of one type to an Optional of another type. If the return value weren't Optional you would use map.
You can see we have eliminated the need for names of return values in favour of naming the parameters of lambda functions. The lambda functions are scoped so you can reuse the names if that's what you want to.
I generally like to provide runnable code, so here is a contrived example of what I mean which is runnable.
import java.util.Optional;
class DummyClass {
private int val = 0;
public void doA(){ val += 1; }
public void doB(){ val += 2; }
public void doC(){ val += 3; }
public Optional<String> maybeAnotherThing(){
return Optional.of(Integer.toString(val));
}
}
public class UseOptional5 {
Optional<DummyClass> maybeGetThing(){
return Optional.of(new DummyClass());
}
String method() {
return maybeGetThing()
// you can put other operations here
.flatMap(val -> {
// eek side effects
val.doA();
val.doB();
val.doC();
return val.maybeAnotherThing();
})
// you can put other operations here too
.orElseThrow(() -> new IllegalArgumentException("fail!!"));
}
public static void main(String args[]) {
UseOptional5 x = new UseOptional5();
System.out.println(x.method());
}
}
Since Java 9 I’d do
void method() {
maybeGetThing().ifPresentOrElse(
usefulVariableName -> {
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// No duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
},
this::doSomethingOnlyHere
);
}
My rule of thumb is you seldom need or want to use isPresent and/or get, they are low-level. For basic things ifPresent (with f) and ifPresetnOrElse are fine. Others are correct that map and flatMap are very useful too.
In most radio devices, we can configure the wave which we want to explore and listen to stations using the demodulation mode compatible with this type.
There are at least two types AM and FM. We can model the radio device in this case as the following:
class RadioDevice {
void demodulate (String m) {
if(m.equals("FM")
/* FM modelation */
else if(m.equals("AM")
/* AM modelation */
}
}
How can I apply the strategy pattern in this case?
Why don't you use polymorphism ?
Make an interface:
interface Radio {
void modulate();
}
And than implement 2 classes:
FMRadio implements Radio{
public void demodule(){
//FM modulation
}
}
AMRadio implements Radio{
public void demodule(){
//AM modulation
}
}
And than, in your main, you could go:
Radio myRadio = new FMRadio();
myRadio.demodule();
If you can have an interface that covers the contract for both AM and FM demodulation, you could use the Strategy pattern:
Demodulator d; // interface Demodulator { byte[] demodulate(); }
switch(m) {
case "AM":
d = new AMDemodulator();
break;
case "FM"
d = new FMDemodulator();
break;
default:
throw new IllegalArgumentException("Unsupported type '"+ m + "'"); // you could use an Enum instead of a String
}
d.demodulate(waves);
This allows you to switch the Demodulator part on the fly while keeping the rest of the program logic in common (no duplication).
Check this repo (not mine) for design patterns and examples: https://github.com/iluwatar/java-design-patterns
To make it a proper Strategy pattern, I would add using a Context class to the previous answer of #Ladislav_M, that will wrap & encapsulate executing a particular strategy and give more flexibility to the code:
class Context {
private Radio radio;
public Context(Radio radio) {
this.radio = radio;
}
public Object runStrategy() {
radio.demodulate();
// do any other stuff you want
return ...
}
}
The execution in main would become more convenient:
Context context = new Context(new FmRadio());
Object result = context.runStrategy();
Or you can inline the above:
Object result = (new Context(new FmRadio())).runStrategy();
Of course, you can choose the implementation of Radio in a switch block and just pass it as a variable to the Context's constructor.
This is not a good use case for Strategy design pattern, its simple inheritance case. Strategy is used where the state of the object does not change but different algorithms apply at different times. e.g. Paypackage computation for different roles of employees (e.g. Temporary, Permanent etc.). Important point here is Temporary employee can become Permanent one day.
In the above case AM will never become FM in its life time. hence Strategy is not right pattern for it. These are (probably) different classes with common behavior (if present) can be shifted to base class. If they show a common contract with clients then even interface will do the task.
I want to make a simple interative shell based on the console where I can write commands like login, help, et cetera.
I first thought of using Enums, but then I didn't know how to implement them neatly without a load of if-else statements, so I decided to go with an array-approach and came up with this:
public class Parser {
private static String[] opts = new String[] {"opt0", "opt1", "opt2", "opt3" ... }
public void parse(String text) {
for(int i = 0; i < opts.length; i++) {
if(text.matches(opts[i]) {
switch(i) {
case 0:
// Do something
case 1:
// Do something-something
case 2:
// Do something else
}
return;
}
}
}
}
But I ended up seeing that this was probably the most rudimentary way of doing something like this, and that there would be problems if I wanted to change the order of the options. How could I make a simpler parser? This way it would work, but it would also have said problems. The use of the program is purely educational, not intended for any serious thing.
A simple approach is to have a HashMap with the key equal to the command text and the value is an instance of class that handle this command. Assuming that the command handler class does not take arguments (but you can easily extend this) you can just use a Runnable instance.
Example code:
Runnable helpHandler = new Runnable() {
public void run(){
// handle the command
}
}
// Define all your command handlers
HashMap<String, Runnable> commandsMap = new HashMap<>(); // Java 7 syntax
commandsMap.put("help",helpHandler);
// Add all your command handlers instances
String cmd; // read the user input
Runnable handler;
if((handler = commandsMap.get(cmd)) != null) {
handler.run();
}
You can easily extend this approach to accept argument by implementing your own interface and subclass it. It is good to use variable arguments if you know the data type e.g. void execute(String ... args)
One solution that comes to mind is actually using Design patterns. You could use the input from the user, as the discriminator for a Factory class.
This factory class will generate an object, with an "execute" method, based on the input. This is called a Command object.
Then you can simply call the method of the object returned from the factory.
No need for a switch statement. If the object is null, then you know the user entered an invalid option, and it abstracts the decision logic away from your input parser.
Hopefully this will help :)
Is there a simple way to clear all fields of an instance from a an instance? I mean, I would like to remove all values assigned to the fields of an instance.
ADDED
From the main thread I start a window and another thread which controls state of the window (the last thread, for example, display certain panels for a certain period of time). I have a class which contains state of the window (on which stage the user is, which buttons he already clicked).
In the end, user may want to start the whole process from the beginning (it is a game). So, I decided. So, if everything is executed from the beginning, I would like to have all parameter to be clean (fresh, unassigned).
ADDED
The main thread, creates the new object which is executed in a new thread (and the old thread is finished). So, I cannot create a new object from the old thread. I just have a loop in the second thread.
I don't get it. How can you programmatically decide how to clear various fields?
For normal attributes it can be easy (var = null) but what about composite things or collection? Should it be collection = null, or collection.removeAll()?
This question is looking for synctactic sugar that wouldn't make so much sense..
The best way is to write out your own reset() method to customize the behaviour for every single object.. maybe you can patternize it using an
interface Resettable
{
void reset()
}
but nothing more than that..
Is there a simple way to clear all fields of an instance from a an instance? I mean, I would like to remove all values assigned to the fields of an instance.
Yes, just assign a default value to each one of them. It would take you about 20-30 mins. and will run well forever*( YMMV)
Create a method: reset and invoke it
class YourClass {
int a;
int b;
boolean c;
double d;
String f;
// and so on...
public void method1(){}
public void method2(){}
public void method3(){}
// etc.
// Magic method, reset all the attributes of your instance...
public void reset(){
a = 0;
b = 0;
c = false;
d = 0.0;
f = "";
}
}
And then just invoke it in your code:
....
YourClass object = new YourClass();
Thread thread = YourSpecificNewThread( object );
thread.start();
... // Later on you decide you have to reset the object just call your method:
object.reset(); // like new
I don't really see where's the problem with this approach.
You may use reflection:
Try something like this:
Field[] fields = object.getClass().getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
f.set(object, null);
}
It's not a beautifull solution, but may work for you.
There is no other way than setting null to all of them.
As an aside, i find that a particular weird idea. You would have better re-creating a new instance, instead of trying to reset your old one.
If you want to clear a filter (Serializable) that your application "can handle his null" fields, you can use BeanUtils (Apache Commons):
Field[] fields = filter.getClass().getDeclaredFields();
for (Field f : fields) {
if (f.getName().endsWith("serialVersionUID")) {
continue;
}
try {
BeanUtils.setProperty(filter, f.getName(), null);
} catch (IllegalAccessException | InvocationTargetException e) {
FacesUtils.handleError(LOG, "Erro limpar filtro...", e);
}
}
I hope it can help you.