views:

162

answers:

4

I'm building a multiprocess architecture that seems to be a strange meld of a pipeline and a chain of responsibility. Essentially, I have a chain of handlers linked up by queues. Each handler will receive an object that represents the input data, forward it to the next handler so that it can start working on it, and then determine if it can do anything with that data.

I don't believe I can call this a pipeline because one step doesn't really depend on the next. This also doesn't seem to be a traditional chain of responsibility because one handler can't prevent other handlers from handling that data. Is there a name for this design that will help me document this architecture? Or am I just going to have to call it something like "Pipeline of Responsibility"?

+1  A: 

This sounds more like the Observer pattern, as each handler is notified that there is a change from the input (via an event that contains the data).

akf
I hadn't thought about it that way. I suppose that makes sense.
Jason Baker
If I understood correctly, he already has a chain of objects instead of some sort of message broadcasting, right?
Padu Merloti
I think the key to the COR pattern is that the event is passed until someone handles it and then it is no longer forwarded. In the OP example, all handlers in the queue process the event, so it is a sort of broadcast.
akf
Ok, I see. Then the only significant difference would be if the order in which the object is received by the handlers is important.
Padu Merloti
Yes. In this example there is a strong ordering which is not present in Observer. I should have been more clear on how I consider Jason's design to *resemble* the Observer as opposed to Chain of Responsibility, while not being a perfect fit.
akf
+2  A: 

From your description, this is something else. Both chain of responsibility and pipeline deal with essentially serial processing. At least if I understand your description correctly, what you have is basically a number of "processor elements" working on the data in parallel.

Normally, you'd handle a situation like that with a set of observers, but your description doesn't really fit the observer pattern either. In particular, each of your processor elements appears to know about (at least) one other processor element. With the observer pattern, the observers are normally oblivious to each other -- each registers itself with the data source, and when there's new/changed data, all the observers are notified by the data source.

My immediate reaction would be that you'd probably be better off using the observer pattern instead of looking for a name for what you've done. One of the points of patterns is to solve similar problems in similar ways. From the sound of things, this would probably be a bit more versatile and manageable. For example, if you decide to eliminate one observer from the chain, you'll apparently have to modify a different observer to do so. With the normal observer pattern, you can add or remove observers without changing any others (and without the others even being aware anything has changed at all).

Edit: Given a mixture of independent and chained elements, I see two possible variants. The first (and probably cleanest) is to use the observer pattern at the top level, and some of the observers will themselves be pipelines.

The other possibility would be to steal a trick from VLIW processors, and at the top level have a flag indicating whether a particular element depends on the result from the previous one or not. That makes it pretty easy to mix pipelines with independent observers, and if (for example) some time you care about doing parallel processing, makes it pretty easy to execute independent processes in parallel, while maintaining serial execution for those that need it.

Jerry Coffin
I think this is a case of choosing between the lesser of two evils. I agree that using an Observer pattern directly is probably best, but there are a couple of stages that *do* constitute a pipeline. And I feel that having them all fit under the same overarching design makes everything more understandable.
Jason Baker
FYI, the alternative would probably be more something like having a component that sends out messages to the observers be the last component in the pipeline. That could work, but I feel (as a matter of opinion) that this setup is the most easily understandable. Bear in mind that this is an architecture that hasn't used concurrency before, so having *some* sequentiality would likely make it easier to understand.
Jason Baker
+1  A: 

I still think it is the chain of responsibility, even with the specific of not stopping the chain.

Several patterns are very similar and they do have variations. I think the best way to see if a pattern fits a case is looking at its intent. From the GoF book:

Chain of Responsibility "Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it." (pg.223)

So if there's no coupling between your handler and the objects going through the chain, I don't think it matters that the object will always fall to the end of the chain, even if handled.

Padu Merloti
A: 

I think this a Blackboard

see this answer to a similar question

Serkan