I want to avoid the using of instanceof:
here is my case :
The definition of my Events classes are in a commons module :
public class Event1 extends AbstractEvent{
}
public class Event2 extends AbstractEvent{
}
public class Event3 extends AbstractEvent{
}
in another module called jms i have a listener that receive Event message from a queue :
public class MyMessageListener implements MessageListener {
#Override
public void onMessage(Message message) {
// CONVERT message to Event Object
if (event instanceof Event1) {
// Execute Processing 1
}
if (event instanceof Event2) {
// Execute Processing 2
}
if (event instanceof Event3) {
// Execute Processing 3
}
}
I want to avoid using instanceof and the best things for doing this is the visitor pattern with an execute method in the AbstractEvent and every leaf classes will implement it .
My problem is that in the common package i don't have access to the classes responsible for the processing . theses classes exist only in the jms module .
Is there any Tips or hint to do this (Advanced Visitor) or another pattern to do that
Put all possible behaviours to Map<Class, Runnable> and match event's type and Runnable type.
In such cases, the visitor Pattern can sometimes help. The visitor pattern is mainly suitable if your class hierarchy doesn't change much, because for each change in the class hierarchy you also must change the visitor (but that is also the case if you're using `instanceof').
To use the visitor pattern, you need to define a Visitor interface which contains a visit method for all types you want to visit:
interface Visitor {
visit(Event1 event);
visit(Event2 event);
visit(Event3 event);
}
first you want a common superclass which is the root for all classes you want to apply the visitor to. This superclass contains a method callVisitor:
public abstract class MyEvent extends AbstractEvent {
public abstract void visit(Visitor v);
}
public class Event1 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event1)
}
}
public class Event2 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event2)
}
}
public class Event3 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event3)
}
}
Finally, you can create a visitor instance every time you need different behaviour based on the runtime type of the class:
public void onMessage(Message message) {
Visitor v = new Visitor() {
public void visit(Event1 event) {
// Execute Processing 1
}
public void visit(Event2 event) {
// Execute Processing 2
}
public void visit(Event3 event) {
// Execute Processing 3
}
}
event.visit(v);
}
The visitor pattern might be overkill in your situation, but I find it useful sometimes. The major advantage over using instanceof and other possible solutions is that it is typesafe: if you add a class to the hierarchy, the project will not compile until you added a visitor method to all visitors you defined.
As an alternative approach to the other answers, you could move the decision logic into your messaging configuration, so that each type of event is consumed by a MessageListener dedicated to processing only one type of Event. This will remove any "if" logic from your Consumer.
A caveat to this approach is that multiple consumers may process the events out of order. If this is an issue for your problem domain you may not wish to deal with the out-of-sequence issues yourself.
See JMS Selectors for more information
The advantages to this approach are:
Consumers are responsible for only one Event type (simplification)
You can add more Consumers independently based on event type (scalability)
You could have the AbstractEvent declare an abstract isOfType() method:
public abstract class AbstractEvent {
public abstract boolean isOfType( String type );
}
It would eliminate the instanceof's but not the if switching, though...
Cheers,
Related
in the reference book "Design Patterns Elements of Reusable Object-Oriented Software" by the gang of four, the intent of the visitor pattern is explained as follow :
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
Another advantage I read about the visitor pattern is that:
ADD A NEW OPERATION WITHOUT HAVING THE SOURCE CODE OF THE CLASSES..
I made a deep search in Google, but I did not find any example showing how to do that.
So let's take a simple example :
public interface MyInterface {
public void myMethod();
}
public class MyClassA implements MyInterface {
/* (non-Javadoc)
* #see com.mycomp.tutorials.designpattern.behavorials.MyInterface#myMethodA()
*/
public void myMethod() {
System.out.println("myMethodA implemented in MyClassA");
}
}
public class MyClassB implements MyInterface {
/* (non-Javadoc)
* #see com.mycomp.tutorials.designpattern.behavorials.MyInterface#myMethodA()
*/
public void myMethod() {
System.out.println("myMethod implemented in MyClassB");
}
}
So how would I add a new method myNewMethod() to this hierarchy of classes without changing them, using the visitor pattern?
You example is not a visitor pattern. It is just inheritance.
A visitor pattern first requires an visitor interface
interface ThingVisitor {
void visit(ThingA a);
void visit(ThingB b);
}
Now you need an interface Thing:
interface Thing {
void accept(ThingVisitor visitor);
}
And your implementation of, for example, ThingA would be
class ThingA implements Thing {
public void accept(final ThingVisitor visitor) {
visitor.visit(this);
}
}
Now you see the logic to handle the Thing types is contained in the implementations of ThingVisitor.
Let's say you have a Message class, and 2 subclasses Email and Sms.
You could have many operations on these two classes, like sendToOnePerson(), sendToSeveralPeople(). But you probably don't want to have these methods in the Email and Sms class directly, because it tightly couples them to the SMTP/phone system. And you would also like to be able to add other operations in the futre, like forward() or delete(), or whatever. So the first implementation you could use is
public void delete(Message message) {
if (message instanceof Email) {
deleteEmail(Email) message);
}
else if (message instanceof Sms) {
deleteSms((Sms) message);
}
}
But this is ugly: it's not object-oriented, and it will fail if there is a new VoiceMessage subclass appearing.
An alternative is to use the visitor pattern.
public interface MessageVisitor {
void visitEmail(Email email);
void visitSms(Sms sms);
}
public abstract class Message {
public void accept(MessageVisitor visitor);
}
public class Email extends Message {
#Override
public void accept(MessageVisitor visitor) {
visitor.visitEmail(this);
}
}
public class Sms extends Message {
#Override
public void accept(MessageVisitor visitor) {
visitor.visitSms(this);
}
}
This way, to implement send(), all you need is a MessageVisitor implementation that can send an email and send an Sms:
SendMessageVisitor visitor = new SendMessageVisitor();
message.accept(visitor);
And if you introduce a new delete() operation, you don't have to touch to Message classes at all. All you need is a DeleteMessageVisitor:
DeleteMessageVisitor visitor = new DeleteMessageVisitor();
message.accept(visitor);
So, basically, it's a bit like if you added polymorphic methods to the Message classes by not actually modifying the Message classes.
The visitor pattern assumes that you have a method in the classes you want to "visit" which accepts and executes the visitor, here is an example. The pattern is not motivated by adding functionality to foreign classes but to localize functionality in the visitors which would otherwise be spread over several classes, e.g. for saving elements (see the example).
Quick description of the visitor pattern.
The classes that require modification must all implement the 'accept' method. Clients call this accept method to perform some new action on that family of classes thereby extending their functionality. Clients are able to use this one accept method to perform a wide range of new actions by passing in a different visitor class for each specific action. A visitor class contains multiple overridden visit methods defining how to achieve that same specific action for every class within the family. These visit methods get passed an instance on which to work
Our legacy code has a long code of if else blocks that depend on events and object type
if(event == A && objectType == O1){
.....
}
else if (event == A && objectType == O2){
....
}
else if (....)
....
....
With more and more conditions introducing, I was thinking of replacing this logic with Command pattern for each condition. But the number of classes required would be (no. of events) * (no. of object types). Is there any simpler way to refactor this code?
Create a class enclosing event and objectType, make it implement .equals() and .hashCode(). Create a generic class for each execution block too.
Then you'll be able to use a Map and a simple lookup will return what is needed to execute.
The pattern you may be looking for is often called double dispatching or sometimes Visitor pattern. http://en.wikipedia.org/wiki/Visitor_pattern
Create a set of classes for events and a set for object types. Create an interface
public interface VisitEvent {
public void visit(EventA eventA);
public void visit(EventB eventB);
// for each event class
}
Within the event class, you have to invoke the visit pattern on the object type class.
public class EventA {
public void visit(ObjectTypeParent otp) {
otp.visit(this);
}
}
Presuming that the object type classes inherit from a common class
public abstract class ObjectTypeParent implements VisitEvent {
public void visit(EventA eventA) {
// default code here
}
// same for each event visit from VisitEvent
}
then
public class ObjectType01 extends ObjectTypeParent {
public void visit(EventA eventA) {
// stuff you want done for this combination
}
// don't implement the ones that have common behavior
}
I am implementing the Observer / Observable pattern using Java. However, I am encountering a problem in the Observer portion of my code.
Observable
public class Model extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<A>());
this.notifyObservers(new ArrayList<B>());
}
}
Observer
public class View implements Observer {
#Override
public void update(Observable observable, Object object) {
// TODO: If object is ArrayList<A>?
System.out.println("A");
// TODO: If object is ArrayList<B>?
System.out.println("B");
}
}
How would I fill in the TODO comments to check for the generic on the ArrayList? Is this even possible? (I would prefer to do it without implementing more classes, if possible.)
An Observable should send one and only one type of data.
public class ModelA extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<A>());
}
}
public class ModelB extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<B>());
}
}
Your other alternative is to put ArrayList<A> and ArrayList<B> into a class. You can notify your observers with that class.
You could use instanceof to see what type is your object but you are misusing the pattern.
The idea is that the Observable has a well defined interface and all the Observer needs to know is to use the API to pass the notification.
Logic to know what exactly is the Observable should not be mixed in the code.
From your question sounds to me you have 2 Observable and they should keep their own listeners interested specifically in them for notification. Not one combined
I have a class MyObserver that listens to changes in Notifier. Notifier extends Observable and notify its events with notifyObservers(Object). The object passed as argument is always an instance of the same class. The problem is that each observer need to listen to diferent events. For example one observer needs to listen to state changed events and others to all types of events. How can I do this with observer pattern?
Thanks.
Use notifyObservers(Object arg) version and create some sort of "event type" object to stick in there. In your observing classes simply filter on the passed in event class.
public void update(Object observable, Object arg) {
if ( (MyEvent) arg.isEventX() ) { /* do stuff */ }
}
I think that the Java built-in implementation of the Observer Pattern is not suitable for your case.
In fact, the general Observer pattern is usable when just one Observable kind of events can arise. In the Observer Design Pattern, all the Observes get notified always.
So, in this case, you need to extend the general Observer pattern, by defining your own Observable interface, for example, this way:
public enum EventKind {
EVENT_A, EVENT_B, EVENT_C;
}
public interface Observable {
public void registerObserver(EventKind eventKind);
public void unregisterObserver(EventKind eventKind);
public void notifyObservers(EventKind eventKind);
}
Then you can just implement this Observable interface with internal lists for each kind of event to notify. You can still use the Java built-in Observer interface if you wish.
This approach has the following benefits:
You can flexibly add more kind of events
without affecting the code of the
Observers.
You can register any observer to any
event.
You update just the Observers
that are effectively interested in
each event.
You avoid "empty methods", "event type checking" and other
tricks on the Observers side.
If you can change the design a bit:
interface MyObserver {
public void stateChangeEvent();
public void otherEvent();
}
class MyObserverAdapter implements MyObserver {
public void stateChangeEvent() {
// some default implementation or no implementation.
}
public void otherEvent() {
// some default implementation or no implementation.
}
}
class MyStateChangeObserver extends MyObserverAdapter {
public void stateChangeEvent() {
// implement behavior specific to this class.
}
}
class MyOtherObserver extends MyObserverAdapter {
public void otherEvent() {
// implement behavior specific to this class.
}
}
Usage:
MyObserver stateObserver = new MyStateChangeObserver();
MyObserver otherObserver = new MyOtherObserver();
notifier.notifyObservers(stateObserver);
notifier.notifyObservers(otherObserver);
You can test for a state change by doing the following in the Observable class:
public void update(Observable o, Object arg)
{
if(o.hasChanged())
{
// do something
}
}
The observers that listen to anything don't need this test. This is probably the easiest way if you only want to listen for state changes.
In Java i have abstract class named Operation and three its subclasses called OperationActivation, OperationPayment and OperationSendEmail.
ADDED FROM COMMENT: Operation* objects are EJB Entity Beans so I can't have business logic inside them.
No I want to create processor class like this:
public class ProcessOperationService {
public void processOperation(Operation operation) {
out.println("process Operation");
process(operation);
}
public void process(OperationActivation operationActivation) {
out.println("process Activation");
}
public void process(OperationPayment operationPayment) {
out.println("process Payment");
}
public void process(OperationSendEmail operationSendEmail) {
out.println("process OperationSendEmail");
}
}
Processing each operation requires different logic so I want to have three different methods , one for each operation.
Of course this code doesn't compile. Am I missing something or it can't be done that way?
You are mixing up overloading and polymorphic method handling. When you overload methods based on the parameter type, that is static polymorphism. Those methods should be called from code that knows at compile-time what the type is. You could possibly do the following, but it wouldn't be clean object-oriented code:
public class ProcessOperationService {
public void processOperation(Operation operation) {
out.println("process Operation");
if (operation instanceof OperationActivation)
process((OperationActivation)operation);
else if (operation instanceof OperationPayment)
process((OperationPayment)operation);
...
}
public void process(OperationActivation operationActivation) {
out.println("process Activation");
}
...
}
It would be much better to let the automatic run-time polymorphism work, by doing as Brian Agnew suggested, and making process be a method of each Operation subtype itself.
Shouldn't your Operation* objects be doing the work themselves ? So you can write (say)
for (Operation op : ops) {
op.process();
}
You can encapsulate the logic for each particular operation in its own class, and that way everything related to OperationPayment remains in the OperationPayment class. You don't need a Processor class (and so you don't need to modify a Processor class everytime you add an Operation)
There are more complex patterns to enable objects to mediate wrt. what they need to execute, but I'm not sure you need something that complex at this stage.
Assumption: Operation* objects are subclasses of Operation
Unless the processOperation(Operation) method is performing some common functionality, you could just remove it and expose the process(Operation) methods.
The Command Pattern (JavaWorld Explanation) might be useful, but it's tricky to tell exactly what properties you want from your question.
The problem with the code is that any object that matches one of the process(Operation*) methods will also match the process(Operation) method. As there are 2 methods that can be used, the compiler is warning you of an ambiguous situation.
If you really want/need the code above, I would suggest implementing the process(Operation*) methods, and modify the process(Operation) method so it is called processCommon(Operation). Then, the first thing each process(Operation*) does is call processCommon.
Alternatively, you can code exactly as Avi said, using instanceof comparisons.
Neither is ideal, but it will accomplish what you want.
So you have an abstract class called 'Operation' and it has 3 classes extending it. Not sure if this is what you are after but I'd imagine it be designed something like this:
Operation.java
public abstract class Operation {
public abstract void process();
}
OperationActivation.java
public class OperationActivation extends Operation {
public void process() {
//Implement OperationActivation specific logic here
}
}
OperationPayment.java
public class OperationPayment extends Operation {
public void process() {
//Implement OperationPayment specific logic here
}
}
OperationSendEmail.java
public class OperationSendEmail extends Operation {
public void process() {
//Implement OperationSendEmail spepcific logic here
}
}
ProcessOperationService.java
public class ProcessOperationService {
public void processOperation(Operation operation) {
out.println("process Operation");
operation.process();
}
}
Won't the Visitor pattern be of use here ?
The class Operation can declare an "accept" method that takes a Visitor object and the subclasses can have provide the implementation :
public interface IOperationVisitor {
public void visit (OperationActivation visited);
public void visit (OperationPayment visited);
public void visit (OperationSendEmail visited);
}
abstract class Operation {
public void accept(IOperationVisitor visitor)();
}
class OperationActivation extends Operation {
public void accept(IOperationvisitor visitor) {
visitor.visit(this);
}
}
Similarly define "accept" method for classes OperationPayment and OperationSendEmail ..
Now your class can implement the visitor :
public class ProcessOperationService implements IOperationVisitor {
public void processOperation(Operation operation) {
operation.accept(this);
}
public void visit (OperationActivation visited) {
// Operation Activation specific implementation
}
public void visit (OperationPayment visited) {
// OperationPayment specific implementation
}
public void visit ((OperationSendEmail visited) {
// (Operation SendEmail specific implementation
}
}