• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

More flexible Strategy

 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
I'm trying to figure out a solution to a problem I have using a form of Strategy.
I'm designing a Report interface which needs to have a different implementation for each customer. Each Report has certain key fields that remain the same, but there are optional fields that are different for each customer, both in type and number.
I have a factory that returns an implementation of Report based on externally configured parameters. The interface has methods like setReportId(), setReportOriginator(), etc. for the core fields.
For the custom fields for different customers, I have a method in the interface setOptionalParameters(Map map) which I am using to populate these extra fields. This gives me the ability to keep the interface, and add as many extra parameters as I need.
However, this design seems a bit clunky to me. Each time I need to add optional parameters, I have to add them to the Map, and then extract and cast them in the interface implementation. This means checking back and forth a lot to make sure I've extracted the right type from the Map, and it is error prone.
I reckon there must be a cleaner way to do this, because it seems like quite a common problem.
Thanks in advance,
Alan
 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Strategy is a neat pattern for this kind of thing. Can you put the code that differs from one customer to another into different classes and invoke them from the main report driver?

Instead of driving the differences through a bunch of parameters, write explicit code for each customer and run the right strategy for each customer. If you watch your dependencies the factory can get new strategies from a configuration file and you can add customers without touching the core code.
Would that work for you?
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You might also get some ideas from http://www.martinfowler.com/apsupp/properties.pdf
 
Alan Sandhurst
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the feedback...
Stan - nice idea...but the problem with writing custom reports for each customer is that what differentiates each customer's report is the parameters that are passed in, both in name and type.
I need a way to actually pass these parameters to the ReportWriter, so I need (as far as I can see) to have a method for this in the interface.
I can do the custom report writing bit- I'm actually doing that right now, using an external property to determine the report format. Some reports are XML based, others are plain text, but I still need these specific parameters
Ilja - thanks for the link- I'll check it out. I'm a fan of Martin Fowler's Refactoring and PEAA.
Alan
 
Stan James
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmmm, then parameter builder strategies!

Again hide knowledge of particular strategies from this routine by loading the factory from configuration files. Make sure you can add new customers without touching this class or the factory.
Any smiles yet?
 
Alan Sandhurst
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the reply....actually that is almost making me smile now This is a variation on one way I had thought of doing this before, which is to pass in a custom parameter object to the ReportWriter, with some of its members not being used.
But your suggestion of using a Strategy to create the param object is nicer - get the appropriate param object from a factory.
There is still a certain amount of danger with this though as I see it, which is probably unavoidable. At some point, clients will have to pass in some kind of list or map of parameters, and without specifying the type for these parameters in the interface, there's no restriction on what they pass in, which is ultimately what I'd like to enforce.
Hmm...
 
blacksmith
Posts: 1332
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Isn't java 1.4 or 1.5 supposed to have generics in it, which should solve the type enforcement problem?
 
Alan Sandhurst
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's not till 1.5 unfortunately, which is too late for me...
 
Ranch Hand
Posts: 268
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I recently ran across a similar problem having to do with different kinds of reports that share enough in common to make it worthwhile to abstract them, but not enough to make it easy. I solved it using the Abstract Factory pattern in combination with the Template Method pattern. So I have a manager that uses a helper, like such:

Then you have subclasses extend Helper, Type1Helper and Type2Helper (for each type of report) and override the methods to do the processing specific to that report type. As long as you abstract the core and optional fields under some kind of type that represents them, you should be able to deal with arrays of ReportField objects (for example) and not have to be concerned with whether they're optional for that particular report type or not.
Another approach you could use here is to pass a Report object through a Chain of Responsibility pattern. You simply let each module do its work on the object, populating whatever parts of it are appropriate and then pass it on to the next module. You can add modules that are customer-specific and separate them from the core modules. You can even break up the customer-specific modules using this approach so that some pieces can be shared by multiple customers.
sev
 
Alan Sandhurst
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's a nice approach too- I like the use of Chain of Responsibility.

At the moment I do use a kind of helper as you outline, with the type specific stuff being fleshed out in each subclass for the given type of report.

The issue of the parameters being passed in is still there though i.e. there is still a necessity at some point to populate some kind of generic parameter object. I think this is unavoidable - the interface has to provide clients with some way of passing in the optional parameters. Using a Map or other collection type, or some custom parameter object, seems the only way to achieve this as far as I can see. It's a bit clunky, but it does provide the flexibility needed.
 
Ranch Hand
Posts: 374
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


This example only provides String handling, but you can repeat the pattern for whatever type you need to--Integer, Double, et al.
[ May 13, 2004: Message edited by: David Hibbs ]
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic