I'm building the mail module for a line-of-business application. The situation is that when sending the mails in response to some input, they should be grouped so a user doesn't receive several consecutive mails with different items but just one with all items included. Also, mails should be grouped by a specific type, that depends on the type of input that created the mail notification, I have the list of inputs, and each one with its specific grouping type, for instance:
Hierarchy: Employee has Processes has Requests has Activities
Activity 1: By Employee (so a receiver will get all notifications of the processes he owns of this activity type in just one mail)
Activity 2: By Process (a receiver will get a group of all notifications of all requests on this process, and this activity type)
Activity 3: By Request (activities of this request will be grouped)
Activity 4: By Activity (each activity will be sent in a separate mail)
This groupings will change constantly.
You may think, well in order to do that inputs should be made at once so mails are generated at the same time and so grouped, otherwise how the system will know when to wait for other inputs and when to just send a separate mail?.. well the answer is both, so what I'm doing is setting a timer so the mail service runs every 5 minutes, some immediate mails might get delayed a few minutes, but that's an affordable trade off.
So I chose to use this Chain of Responsability Design Pattern and here's the structure:
So I have two interfaces IGroupingType which defines how each type should be, and has 2 methods: CalculateGrouping()
: determines if this is the grouping of the activity. GroupEmailsToSend()
: if this is the grouping, gets the mails list.
Interface IGroupingHandler is the service class that will call each grouping type, the GetGroupingResult()
just calls the 2 methods on the IGroupingType concrete implemetations, first CalculateGrouping()
to get the correct grouping, when it finds it, calls the GroupEmailsToSend()
. This interface also registers the next node in the chain for each grouping.
The grouping Enum is just for returning the result of grouping calculations.
And then there's also the EndOfChainSendingGrouping class, in case no grouping was found I'll just send the mail right away.
Basicaly I just need some advice on this structure, since I'm kind of new to this pattern, does it have any pitfalls? is there something I can improve? or is there a better way to accomplish this?
Thanks in advance..
The chain-of-responsibility pattern is structurally nearly identical to the decorator pattern, the difference being that for the decorator, all classes handle the request, while for the chain of responsibility, exactly one of the classes in the chain handles the request.
Each of the composites will return a series of handlers for desired chain of responsibility. Although this example is really only complicating a simpler Chains of Responsibility, where the SomeSystem could be initiated with the chains themselves. Although keeping them packaged may be helpful.
For example, an ATM uses the Chain of Responsibility design pattern in money giving process. In other words, we can say that normally each receiver contains reference of another receiver. If one object cannot handle the request then it passes the same to the next receiver and so on.
Decorators provide a flexible alternative to subclassing for extending functionality. I'd say its around the order in which things will happen. If you chain them, the will be called along the chain. With a decorator you're not guaranteed this order, only that additional responsibilities can be attached.
I think chaining sounds good and seems to be the best fitting here. Eventually the Decorator pattern could be used for filtering the receiver lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With