views:

134

answers:

3

So, I've come back to ask, once more, a patterns-related question. This may be too generic to answer, but my problem is this (I am programming and applying concepts that I learn as I go along):

I have several structures within structures (note, I'm using the word structure in the general sense, not in the strict C struct sense (whoa, what a tongue twister)), and quite a bit of complicated inter-communications going on. Using the example of one of my earlier questions, I have Unit objects, UnitStatistics objects, General objects, Army objects, Soldier objects, Battle objects, and the list goes on, some organized in a tree structure.

After researching a little bit and asking around, I decided to use the mediator pattern because the interdependencies were becoming a trifle too much, and the classes were starting to appear too tightly coupled (yes, another term which I just learned and am too happy about not to use it somewhere). The pattern makes perfect sense and it should straighten some of the chaotic spaghetti that I currently have boiling in my project pot.

But well, I guess I haven't learned yet enough about OO design. My question is this (finally. PS, I hope it makes sense): should I have one central mediator that deals with all communications within the program, and is it even possible? Or should I have, say, an abstract mediator and one subclassed mediator per structure type that deals with communication of a particular set of classes, e.g. a concrete mediator per army which helps out the army, its general, its units, etc.

I'm leaning more towards the second option, but I really am no expert when it comes to OO design. So third question is, what should I read to learn more about this kind of subject (I've looked at Head First's Design Patterns and the GoF book, but they're more of a "learn the vocabulary" kind of book than a "learn how to use your vocabulary" kind of book, which is what I need in this case.

As always, thanks for any and all help (including the witty comments).

+1  A: 

I can't answer your question directly, because I have never used that design pattern. However, whenever I have this problem, of message passing between various objects, I use the signal-slot pattern. Usually I use Qt's, but my second option is Boost's. They both solve the problem by having a single, global message passing handler. They are also both type-safe are quite efficient, both in terms of cpu-cycles and in productivity. Because they are so flexible, i.e. any object and emit any kind of signal, and any other object can receive any signal, you'll end up solving, I think, what you describe.

Sorry if I just made things worse by not choosing any of the 2 option, but instead adding a 3rd!

Gianni
I read those links on 'signal slot' pattern. Looks to me a lot like the pattern more commonly known as 'observer pattern'. Sound familiar?
FastAl
Yeah, I know that patter also; and yeah, maybe they could be used for similar purposes, but they are different, in that the signal-slot thing, every object is independent and knows nothing of any other object. They either just receive a certain signal or emit one (or both). whether any one else is actually emitting or listening for those signals doesn't matter. An observer is designed specifically to listen for one thing, an object that has a slot might not be.
Gianni
Thanks for the pointer to the Boost Signal library. Never used it, but seems very useful.
Kristian D'Amato
I guess, the point is, don't try to learn *every* design pattern there is. Most are only useful for very few problems. Try picking a few, like signal-slot or mediator, that can apply not only on the problem at hand, but can be useful for many more, so you can specialize in a few and still be productive. Signal-slot is one of those, MVC is another. That's why Signal-slot and MVC are the foundations of Qt.
Gianni
+1  A: 

I don't think you've provided enough info above to be able to make an informed decision as to which is best.

From looking at your other questions it seems that most of the communication occurs between components within an Army. You don't mention much occurring between one Army and another. In which case it would seem to make sense to have each Mediator instance coordinate communication between the components comprising a single Army - i.e. the Generals, Soldiers etc. So if you have 10 Army's then you will have 10 ArmyMediator's.

If you really want to learn O-O Design you're going to have to try things out and run the risk of getting it wrong from time to time. I think you'll learn just as much, if not more, from having to refactor a design that doesn't quite model the problem correctly into one that does, as you will from getting the design right the first time around.

Often you just won't have enough information up front to be able to choose the right design from the go anyway. Just choose the simplest one that works for now, and improve it later when you have a better idea of the requirements and/or the shortcomings of the current design.

Regarding books, personally I think the GoF book is more useful if you focus less on the specific set of patterns they describe, and focus more on the overall approach of breaking classes down into smaller reusable components, each of which typically encapsulates a single unit of functionality.

jon hanson
Armies may need to send messages to each other as well. So in that case, you might add a global mediator for all armies? If so, it makes sense.
Kristian D'Amato
Yep. I imagine the communication would still be via the Army Mediator.
jon hanson
+1  A: 

In order to use Mediator you need to determine: (1) What does the group of objects, which need mediation, consist of? (2) Among these, which are the ones that have a common interface?

The Mediator design pattern relies on the group of objects that are to be mediated to have a "common interface"; i.e., same base class: the widgets in the GoF book example inherit from same Widget base, etc.

So, for your application: (1) Which are the structures (Soldier, General, Army, Unit, etc.) that need mediation between each other? (2) Which ones of those (Soldier, General, Army, Unit, etc.) have a common base?

This should help you determine, as a first step, an outline of the participants in the Mediator design pattern. You may find out that some structures in (1) fall outside of (2). Then, yo may need to force them adhering to a common interface, too, if you can change that or if you can afford to make that change... (may turn out to be too much redesigning work and it violates the Open-Closed principle: your design should be, as much as possible, open to adding new features but closed to modifying existent ones).

If you discover that (1) and (2) above result in a partition of separate groups, each with its own mediator, then the number of these partitions dictate the number of different types of mediators. Now, should these different mediators have a common interface of their own? Maybe, maybe not. Polymorphism is a way of handling complexity by grouping different entities under a common interface such that they can be handled as a group rather then individually. So, would there be any benefit to group all these supposedly different types of mediators under a common interface (like the DialogDirector in the GoF book example)? Possibly, if: (a) You may have to use a heterogeneous collection of mediators; or (b) You envision in the future that these mediators will evolve (and they probably will). Hence providing an abstract interface allows you to derive more evolved versions of mediators without affecting existent ones or their colleagues (the clients of the mediators).

So, without knowing more, I'd have to guess that, yes, it's probably better to use abstract mediators and to subclass them, for each group partition, just to prepare yourself for future changes without having to redesign your mediators (remember the Open-Closed principle).

Hope this helps.

blue scorpion
It does, thanks!
Kristian D'Amato