|
Prev: How to document a report just like a Class Diagram or Use Case diagram gets analyzed, described and documented in UML?
Next: Call for Papers: The 2008 International Conference of Computer Science and Engineering (ICCSE 2008)
From: Christopher on 20 Nov 2007 19:21 originally posted in comp.lang.c++ and referred here: The observer pattern itself is easy enough. I've implemented it using a Event that contains data for any Event type I forsee my application using. My problem is I don't want one and only one general purpose type of Event. I want to write my design in such a way that more Event Types can be created and used down the road as needed. How can you design the Events in such a way that more can be handled later by the same Observer and Subject classes when they don't know what your Events look like right now? I thought about using an enum or string Identifier in the Base Event class to tell which of the derived Events to cast to, but that is no good, because every time someone makes a new derived class they have to modify a seperate library. yucky.
From: Daniel Pitts on 20 Nov 2007 19:54 Christopher wrote: > originally posted in comp.lang.c++ and referred here: > > The observer pattern itself is easy enough. I've implemented it using > a Event that contains data for any Event type I forsee my application > using. My problem is I don't want one and only one general purpose > type of Event. I want to write my design in such a way that more Event > Types can be created and used down the road as needed. How can you > design the Events in such a way that more can be handled later by the > same Observer and Subject classes when they don't know what your > Events look like right now? > > I thought about using an enum or string Identifier in the Base Event > class to tell which of the derived Events to cast to, but that is no > good, because every time someone makes a new derived class they have > to modify a seperate library. yucky. How about this, follow the Java example and make every type event have a corresponding type of Listener. Your event sources would have addFooListener(FooListener) and your FooListener has a fooHandler(FooEvent) Repeat the process for BarEvent events. -- Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Christopher on 20 Nov 2007 21:08 On Nov 20, 7:54 pm, Daniel Pitts <newsgroup.spamfil...(a)virtualinfinity.net> wrote: > Christopher wrote: > > originally posted in comp.lang.c++ and referred here: > > > The observer pattern itself is easy enough. I've implemented it using > > a Event that contains data for any Event type I forsee my application > > using. My problem is I don't want one and only one general purpose > > type of Event. I want to write my design in such a way that more Event > > Types can be created and used down the road as needed. How can you > > design the Events in such a way that more can be handled later by the > > same Observer and Subject classes when they don't know what your > > Events look like right now? > > > I thought about using an enum or string Identifier in the Base Event > > class to tell which of the derived Events to cast to, but that is no > > good, because every time someone makes a new derived class they have > > to modify a seperate library. yucky. > > How about this, follow the Java example and make every type event have a > corresponding type of Listener. Your event sources would have > addFooListener(FooListener) and your FooListener has a > fooHandler(FooEvent) Repeat the process for BarEvent events. > > -- > Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/> I guess that I am trying to avoid having class declarations like class A : public ListenerB : public ListenerC : public ListenerD : public ListenerE......: public Listener Z I also had hopes of sorting the events by time and placing them all inside one container, but I think I can achieve that with a base event type. It may still be the best way so far. Thanks.
From: Patrick May on 20 Nov 2007 21:31 Christopher <cpisz(a)austin.rr.com> writes: > The observer pattern itself is easy enough. I've implemented it > using a Event that contains data for any Event type I forsee my > application using. My problem is I don't want one and only one > general purpose type of Event. I want to write my design in such a > way that more Event Types can be created and used down the road as > needed. How can you design the Events in such a way that more can be > handled later by the same Observer and Subject classes when they > don't know what your Events look like right now? I'm not sure I understand the problem you're trying to address. If all of your events inherit from the (abstract) base Event class, then you can pass any instance of one of those classes to an Observer that accepts Event objects. If you want to execute logic that is specific to a particular subtype of Event without modifying your Observer implementation, you have a few options. One is to encapsulate the behavior in the Event subtype and simply call a method like execute() on the Event object when it is received. Another, more flexible option is to use the Chain of Responsibility pattern to register Event handlers dynamically. > I thought about using an enum or string Identifier in the Base Event > class to tell which of the derived Events to cast to, but that is no > good, because every time someone makes a new derived class they have > to modify a seperate library. yucky. Tres yucky. I've used Chain of Responsibility to decouple implementation from interface in several large systems. It's easier in languages that allow dynamic loading of new classes, but can be done in C and C++ with dlopen and friends. Applying the pattern in a service oriented system is even easier. Regards, Patrick ------------------------------------------------------------------------ S P Engineering, Inc. | Large scale, mission-critical, distributed OO | systems design and implementation. pjm(a)spe.com | (C++, Java, Common Lisp, Jini, middleware, SOA)
From: Daniel Pitts on 20 Nov 2007 23:33
Christopher wrote: > On Nov 20, 7:54 pm, Daniel Pitts > <newsgroup.spamfil...(a)virtualinfinity.net> wrote: >> Christopher wrote: >>> originally posted in comp.lang.c++ and referred here: >>> The observer pattern itself is easy enough. I've implemented it using >>> a Event that contains data for any Event type I forsee my application >>> using. My problem is I don't want one and only one general purpose >>> type of Event. I want to write my design in such a way that more Event >>> Types can be created and used down the road as needed. How can you >>> design the Events in such a way that more can be handled later by the >>> same Observer and Subject classes when they don't know what your >>> Events look like right now? >>> I thought about using an enum or string Identifier in the Base Event >>> class to tell which of the derived Events to cast to, but that is no >>> good, because every time someone makes a new derived class they have >>> to modify a seperate library. yucky. >> How about this, follow the Java example and make every type event have a >> corresponding type of Listener. Your event sources would have >> addFooListener(FooListener) and your FooListener has a >> fooHandler(FooEvent) Repeat the process for BarEvent events. >> >> -- >> Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/> > > I guess that I am trying to avoid having class declarations like > class A : public ListenerB : public ListenerC : public ListenerD : > public ListenerE......: public Listener Z > > I also had hopes of sorting the events by time and placing them all > inside one container, but I think I can achieve that with a base event > type. > > It may still be the best way so far. Thanks. I can see why you would want to avoid that. Makes me realize the beauty of anonymous inner classes in Java :-) The problem is that any runtime information you might add to the event (such as an EventType token) is likely to cause a few "switch" statements (or switch like constructs), and that is often (not always) an indication of poor-OO design. The decision of which behavior to invoke should usually be polymorphic or delegated, not flowing-conditionals. Unless your in lisp :-) It might be better to group similar events and have one or few Listener classes that have default noop virtual functions for the event handlers. This is similar to the visitor pattern, and could even be implemented as such on the event dispatcher: void FooEvent::dispatchEventTo(Listener &listener) { listener.foo(*this); } void BarEvent::dispatchEventto(Listener &listener) { listener.bar(*this); } Warning, this may be a Java centric approach. -- Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/> |