views:

147

answers:

3

Hi all,

i have to build some financial data report, and for making the calculation, there are a lot of 'if then' situations: if it's a large client, subtract 10%, if it's postal code equals '10101', add 10%, if the day is on a saturday, make a difficult calculation etc.

so i once read about this kind of example, and what they did was (hope i remember well) create a class with some base info and make it possible to add all kinds of calculationobjects to it.

So to put what i remembered in pseudo code

Basecalc bc = new baseCalc();
//put the info in the bc so other objects can do their if
bc.Add(new Largecustomercalc());
bc.Add(new PostalcodeCalc());
bc.add(new WeekdayCalc());

the the bc would run the Calc() methods of all of the added Calc objects. As i type this i think all the Calc objects must be able to see the Basecalc properties to correctly perform their calculation logic.

So all the if's are in the different Calc objects and not ALL in the Basecalc.

does this make sense?

I was wondering if this is some kind of design pattern?

+1  A: 

There seem to be two patterns at work there, depending on what you're looking at. If you're talking about the work delegation to a list of items via a standard "calculate" method, then that's an example of Command pattern. If you're talking about the implementation of the calculator classes, that's Decorator pattern.

Stefan Kendall
+3  A: 

Seems like the Strategy pattern for me. Mixed with the Composite pattern perhaps, as you can add the Calculation implementations to your object.

herzmeister der welten
i've read this about the strategy:"More simply put, an object and its behaviour are separated and put into two different classes. This allows you to switch the algorithm that you are using at any time."that sounds what i want to do, i'll check the composite too
Michel
I was thinking Strategy + Composite too.
Damian Powell
+4  A: 

As dtb suggested, Chain of Responsibility seems most applicable here, with a slight variation: Typically, Chain of Responsibility finds exactly one handler, then exits. If a large customer ordered on Saturday, you'd need to execute two handlers. Note that doing so is a non-trivial extension, because your object might have changed in the mean time and the ordering of handlers becomes relevant. This can be very tricky. E.g. what if there is a $10 discount and a 10% discount? Now the order of operations makes a difference, unless both work on the original price. You get the idea I guess.

It is important to realize that design patterns aren't clear-cut, so there is typically not the one correct answer. Still I believe this is very close to Chain of Responsibility and further from the other patterns that have been mentioned.

First, it is desirable to have concrete implementations perform the check whether they are actually applicable to the item at hand, which is typical for Chain of Responsibility.

Secondly, what you need will behave differently depending on the actual data in your object. The Strategy pattern simply encapsulates different algorithms that essentially achieve the same thing (i.e. you could have different strategies to calculate a 10% discount, but they should all yield the same value).

The Command pattern is a decoupling pattern for the actual request to perform an operation, e.g. if you wanted to have somebody else calculate the discount, you'd spawn a Command object for that. In fact, the handlers of (multicast) events are often Chains of Responsibility.

The Composite pattern is made for tree-like structures where you can compose objects much like you would in the real world. This is related to the issue mentioned before: If you represent your Chain of Responsibility as a degenerate subtree (without branches), you'll have an ordered list and you can represent the difference between subtract $10 first, then 10% or the other way around. In this sense, it could be understood as a highly degenerate Composite. The Composite could be used to describe a specific discounting scheme. Still, selecting and applying the scheme would be Chain of Responsibilities' job.

Like I said, these are not clear-cut terminologies, they are strongly related to each other, often found in variations (and in abuse) and, most importantly, every pattern needs some alterations for your specific problem. Still, I'd prefer to stick to the terminology of Chain of Responsibility with a few variations, because I believe it's closest to the situation you describe.

mnemosyn
<bow>right! ordering had to be in the question as well.Thanks very much for your extensive answer!</bow>
Michel