I have written custom dispathing/handling event system that generally look like this:
Event handler interface:
public interface EventHandler{
}
Base event class:
public abstract class Event<H extends EventHandler> {
public static Class Type<H> { }
public abstract void dispatch(H handler);
}
Handler manager:
public class HandlerManager {
private Map<Event.Type, List<EventHandler>> map = new HashMap<Event.Type, List<EventHandler>>();
public void register(Event.Type<H> type, H handler) {
if(map.get(type) == null) { map.put(type, new ArrayList<EventHandler>()); }
map.get(type).add(handler);
}
public void fire(Event<H> event) {...}
...
}
And everything is working fine but i want to use events like
public class DataChangeEvent<D> extends Event<DataChangeHandler<D>> {
public static final Type<?> TYPE = new Type<?>();
D data;
...
public void dispatch(DataChangeHandler<D> handler) {
handler.onDataChanged(this);
}
public D getData() { return data; }
}
public class DataChangeHandler<D> extends EventHandler {
void onDataChanged(DataChangeEvent<D> event);
}
and now when I register handler DataChangeHandler with manager that generates events for Strings and for example for Integers, this registered handler will receive both events what causes ClassCastException to occure when I want to read data.
I understand that generic dont have some special class and that despite of type defined in DataChangeHandler they are stored in the same list in handlers map.
Is there any way to make it work?
This seems like a really, really smelly design. Why should an event be typed with the class that handles that type of event? That's backwards. An EventHandler should be typed with the type of Events it handles.
So I didn't quite follow what you're actually trying to do but I think you're basically trying to do this:
private Map<Class<?>, List<EventHandler>> map;
public <T> void register(Class<? extends T> typeFilter, EventHandler<T> handler) {
map.get(typeFilter).add(handler);
}
//...later
//safe since we used a generic method to add
#SuppressWarnings("unchecked");
public void fire(Event<?> event) {
for ( EventHandler handler : map.get(event.getClass()) ) {
handler.onDataChanged(event);
}
}
//or similarly:
#SuppressWarnings("unchecked");
public void fire(Event<?> event) {
for ( Class<?> type : map.keySet() ) {
if ( !type.instanceOf(event) ) continue;
for ( EventHandler handler : map.get(type) ) {
handler.onDataChanged(event);
}
}
}
This type of design will filter out events that the handler can't handle.
Generics are largely a compile time feature. If you need the type at runtime you need to pass the class as an arguement and store it in a field.
IMHO: A more elegent way of creating a dispacter is to use an annotation. Like
#EventHandler
public void onMyEvent(MyEvent event) {
// is called when MyEvent is dispacted.
}
Related
Suppose i have an interface
public interface Action<T> {
void doWork(T t);
//can have multiple methods
}
Now this class is implemented by
public class DefaultAction implements Action<String> {
#Override
public void doWork(String s) {
System.out.println(s);
}
}
Now i have a flow which accepts action
public abstract class Flow<T> {
void execute(T t){
Action<T> action = getAction();
action.doWork(t);
}
abstract Action<T> getAction();
}
so i have flow that accepts double
public class AnotherActionFlow extends Flow<Double> {
#Override
Action<Double> getAction() {
return new AnotherActionSet();
}
}
which in turn uses the default action
public class AnotherActionSet implements Action<Double> {
DefaultAction defaultAction;
#Override
public void doWork(Double aDouble) {
defaultAction.doWork(String.valueOf(aDouble));
}
}
So in this case i have to always update the AnotherActionSet method whenever the action interface changes
Is their any workaround so that i can have the common logic to convert the double to string and then use the DefaultAction
Can any pattern help to convert the AnotherActionSet to DefaultAction in which i only specify String.valueOf(aDouble) so the values can be passed to DefaultAction
instead of writing same thing for every method
Summary
I want to reuse use the logic inside the DefaultAction for other actions which are a wrapper around the DefaultAction
For eg;
public class AnotherActionSet2 implements Action<Long> {
DefaultAction defaultAction;
#Override
public void doWork(Long long) {
defaultAction.doWork(String.valueOf(long));
}
}
public class AnotherActionSet3 implements Action<Integer> {
DefaultAction defaultAction;
#Override
public void doWork(Integer int) {
defaultAction.doWork(String.valueOf(int));
}
}
As you can see i have to write the mapping each time manually, instead is it possible to just pass the function which converts the give class to string and then i can use DefaultAction
So i just define Function<Double,String> dToS and plug it to DefaultAction and don't need to define the method again
You can use Java 8 lambda to get something that is much easier and more expressive.
Basically your Action is the same as standard Consumer from JDK, only that the name of the method change.
Then defaultAction look like that:
Consumer<String> defaultAction = s -> {System.out.println(s);}
And so AnotherActionSet can be expressed like that:
Consumer<Double> anotherActionSet = s -> {defaultAction.accept(String.valueOf(aDouble));}
You also discover that flow and action are doing exactly the same (taking a T and returning nothing) so one of the notion is redundant. And you could write:
Consumer<Double> anotherActionFlow = anotherActionSet;
I am wondering if i can replace the generic type upon class initialization ( without inheritance ).
The case is as below .
I have bunch of generic actor + builder class in my module and distribute this to people who wants to use it in my team while keeping the actor and the entry point of fluent interface generic.
The requirement is how can people supply their own builder ( not extending ) to do the stuff they want.
Current state:
class MessageBuilder {
public MessageBuilder msg(String msg) {
//do something
}
}
class Actor {
public MessageBuilder newMessage() {
return new MessageBuilder();
}
}
class Main {
#Test
public void testActor() {
Actor actor = new Actor();
actor.newMessage().msg("sss").send();
}
}
Desired state:
class MessageBuilder{
public MessageBuilder msg(String msg) {
//do something
}
//more fluent api...
}
// project specific - dont want to extend from generic one as this should be contains its own fluent interface
class MyCustomMessageBuilder {
public MyCustomMessageBuilder rawstr(String rawstr) {
//do something
}
}
class Actor<T> {
public T newMessage() {
return (T)builderFactory.getInstance();
}
}
class Main {
#Test
public void testActor() {
Actor<MyCustomMessageBuilder> actor = new Actor(BuilderFactory);
actor.newMessage().rawstr("sss").send();
}
}
It's not possible without some known tricks.
First, Java implements Generics with type erasure (more information on type erasure), therefore the compiler will:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
In practice, this means that Actor<Builder1> and Actor<Builder2> are the exact same class after it gets compiled. In both cases, newMessage is implemented as follows:
class Actor {
public Object newMessage() {
...
}
}
It's not possible for newMessage to have different implementations based on the type parameter and it's not possible for newMessage to ask for the type of T because it gets removed.
Having said that, you can pass in type information:
class Actor<T> {
private Class<T> klass;
public Actor(Class<T> klass) {
this.klass = klass;
}
public T newMessage() {
return klass.newInstance();
}
}
class Main {
#Test
public void testActor() {
Actor<MyCustomMessageBuilder> actor = new Actor<>(MyCustomMessageBuilder.class);
actor.newMessage().rawstr("sss").send();
}
}
I'd go with a factory approach. The builder should be supplied by a factory:
class Actor<MsgBuilder> {
private final Supplier<MsgBuilder> messageBuilderFactory;
public Actor(Supplier<MsgBuilder> builderFactory) {
this.messageBuilderFactory = builderFactory;
}
public MsgBuilder newMessage() {
return messageBuilderFactory.get();
}
}
This way offers flexibility in creating the message builder without sacrificing type safety and also no need for ugly casting.
I have a class that contains several overloaded methods, such as:
interface SharedInterface
{
public void commonMethod();
}
class Model1 implements SharedInterface
{
public void commonMethod(){}
public int foo(){ return 1; }
}
class Model2 implements SharedInterface
{
public void commonMethod(){}
public String bar(){ return "2"; }
}
class Client
{
private ExternalClass external = new ExternalClass();
public void handle( Model1 model )
{
external.calculate( model.foo() );
}
public void handle( Model2 model )
{
external.calculate( model.bar() );
}
}
I want to make the Client class more generic so that it can handle any type of Model in the future. However, because each Model has its own specific public methods, the Client.handle() method needs to change its behaviour according to the given Model. For example, if a Model1 instance is given, then call the method foo() of that model; if a Model2 instance is given, then call the method bar(), etc. In the future more types of models will be created. The following solution breaks the open closed principle and seems like a very bad practice:
class Client
{
private ExternalClass external = new ExternalClass();
public void handle( SharedInterface model )
{
if( model instanceof Model1 )
external.calculate( model.foo() );
else if( model instanceof Model2 )
external.calculate( model.bar() );
}
}
I am thinking of using Generics but I am not sure how generics could solve this.
Please note that the Client class has dependencies (makes use of libraries). The Models have to be POJOs without any dependencies to any other class. Therefore, because of the fact that the implementation of Client.handle() makes use of these dependencies, the method cannot be moved inside the Model classes.
Could someone please provide some alternatives?
Visitor design pattern best suits your problem... Link can help you out
https://sourcemaking.com/design_patterns/visitor..
Your handling logic is different for each type and the different behavior has to be described somewhere, for each Model you add, you have to have a piece of handling logic, this is a perfect case for overloading -- which you already do in your first code bit.
If you're dead set on keeping Client clear of those implementations. You can define the different handling logic in wrappers (adapters) for your data POJOs and pass those to handle(), e.g.:
class Client {
private ExternalClass external = new ExternalClass();
public void handle(PojoAdapter<?> model) {
model.getExecuted(external);
}
}
// Actually, generics are not necessary here, just to
// avoid declaring the same model field with different type
// in each implementation
abstract class PojoAdapter<T extends SharedInterface> {
protected T model;
public PojoAdapter(T model) {
this.model = model;
}
public abstract void getExecuted(ExternalClass excls);
}
class Model1Adapter extends PojoAdapter<Model1> {
#Override public void getExecuted(ExternalClass excls) {
external.calculate(model.foo());
}
}
class Model2Adapter extends PojoAdapter<Model2>{
#Override public void getExecuted(ExternalClass excls) {
external.calculate(model.bar());
}
}
I'm trying to create a simple way to fire CRUD-type events for different domain classes. I've created the following event class:
public class EntityModifiedEvent<E> extends Event<EntityModifiedEventHandler<E>> {
private E element;
private ModType modType;
private Class<E> clazz;
private static Map<String,GwtEvent.Type<EntityModifiedEventHandler<?>>> types = new HashMap<String, GwtEvent.Type<EntityModifiedEventHandler<?>>>();
public EntityModifiedEvent(ModType modType, E element, Class<E> clazz) {
this.element = element;
this.modType = modType;
this.clazz = clazz;
}
public Type<EntityModifiedEventHandler<?>> getType() {
return getType(clazz);
}
#SuppressWarnings({"rawtypes", "unchecked"})
public static GwtEvent.Type<EntityModifiedEventHandler<?>> getType(Class clazz) {
GwtEvent.Type type = types.get(clazz.toString());
if (type == null) {
type = new GwtEvent.Type<EntityModifiedEventHandler<?>>();
types.put(clazz.toString(), type);
}
return type;
}
public E getElement(){
return element;
}
public ModType getModType() {
return modType;
}
#SuppressWarnings({"unchecked", "rawtypes"})
#Override
public Type<EntityModifiedEventHandler<E>> getAssociatedType() {
return (Type) getType();
}
#Override
protected void dispatch(EntityModifiedEventHandler<E> handler) {
handler.onEntityModified(this);
};
public interface EntityModifiedEventHandler<E> extends EventHandler {
void onEntityModified(EntityModifiedEvent<E> entityModifiedEvent);
}
So, any class can register itself as a listener as follow:
getEventBus().addHandler(EntityModifiedEvent.getType(MyDomainClass.class), this);
And the events will be fired like:
getEventBus().fireEventFromSource(new EntityModifiedEvent<MyDomainClass>(ModType.CREATE, instanceModified, MyDomainClass.class), this);
ModType is just a simple Enum with the different types of modifications.
I have some concerns about having a map with all class.toString->eventTypes in this class itself. Do you think this will bring performance issues?
Also, this approach relies on the EventBus using Type object's hashcode to identify the handlers registered for that type (see getType(Class clazz) function). Do you think it's wrong to rely on it?
Any other suggestion about how to do this? Any comment will be much appreciated!
You have to ask yourself what do you gain from such an approach?
Performance - no. I don't have solid numbers on this (I'd have to be able to profile your application), but it's seems that this offers no measurable performance gains, if any. The number of fired events will be the same, but the number of receivers will be greater than with a more fine-grained approach. Plus, there's the type checking.
The ability to perform some common code when any entity modified event is fired, regardless of its type. This is true, but read on on how to achieve it with specific events.
Using specific events for the exact operation that was performed seems like a better choice:
It makes it clear who listens to what event.
The events can have extra metadata specific to the event (how many records where deleted, do you need to flush the cache, etc.)
I'd recommend looking at gwteventbinder to trim some of the boilerplate and improve your code. It also allows for handling several events in one method:
class SuperEvent extends GenericEvent { }
class EventOne extends SuperEvent { }
class EventTwo extends SuperEvent { }
class FormPresenter {
interface MyEventBinder extends EventBinder<FormPresenter> {}
private final MyEventBinder eventBinder = GWT.create(MyEventBinder.class);
FormPresenter(EventBus eventBus) {
eventBinder.bindEventHandlers(this, eventBus);
}
#EventHandler
void onEventOne(EventOne event) {
// handler for EventOne
}
#EventHandler(handles = {EventOne.class, EventTwo.class})
void onEventOneAndTwo(SuperEvent event) {
// handler for EventOne and EventTwo
}
#EventHandler(handles = {EventOne.class, EventTwo.class})
void onEventOneAndTwo2() {
// handler for EventOne and EventTwo without parameter
}
}
Here's the sort of thing I'm trying to do:
class Foo {
private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects
//...
void process(int wIndex) {
process(things.get(wIndex);
}
private void process(WidgetA w) {
//Do things
}
private void process(WidgetB w) {
//Do other things
}
private void process(WidgetAB w) {
//Do completely different things
}
}
abstract class Widget {
//...
}
class WidgetA extends Widget {
//...
}
class WidgetB extends Widget {
}
class WidgetAB extends WidgetA {
}
Basically, a separate class gets an array index from user input, and passes it to the process(int) method, which is supposed to kick off a type-specific process() method to process the object at the passed index. The problem is that the objects are treated as Widget objects, not WidgetA, etc. I could loop through the types using instanceof, I guess, but I'm trying to avoid using that.
The logic in the process() methods needs to access private fields in the Foo class, so moving them to the Widget subclasses might not be the best idea.
So the question is, is there a way for the correct process() method to be called for a given Widget subtype, without using instanceof?
Yes, have a look at the Visitor pattern - also known as double dispatch.
Another potential solution is to use Java's reflection API's. Example:
class Foo {
private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects
//...
void process(int wIndex) {
Widget theWidget = things.get(wIndex);
try {
Class type = theWidget.getClass();
Class[] arg_types = new Class[]{type};
this.getMethod("process", arg_types).invoke(this, theWidget);
} catch (Exception e) {
//Could be SecurityException or NoSuchMethodException
}
}
private void process(WidgetA w) {
//Do things
}
private void process(WidgetB w) {
//Do other things
}
private void process(WidgetAB w) {
//Do completely different things
}
}
abstract class Widget {
//...
}
class WidgetA extends Widget {
//...
}
class WidgetB extends Widget {
}
class WidgetAB extends WidgetA {
}
The issue here being that you have to have defined a process() method for each type of object in the things list or an exception will be thrown at run-time. The compiler will not warn you if you are missing an implementation.