• 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
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Strategy Design Question

 
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,

I have a fee calculation that can be computed one of four different ways. So, I am thinking I need to create an ICalculateFee interface, which exposes a Calculate() method. There are two params that are needed by all the different fee calculations, but most of them need a few more paramaters. I'm trying to figure out what is the best way to accomodate this. Should the param is takes in be another interface or should i let each concrete class specify the additional args.

Any suggestions would be great!
 
Ranch Hand
Posts: 260
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Marco K Paul:
Hello,

Should the param is takes in be another interface or should i let each concrete class specify the additional args.



If the interface is used by a client program to pass parameters(Say user supplied input values) to the one of the 4 calculating algorithms then you could have the calculate method take 3 paramters in the interface, 2 of which are common to all the implementing classes and one of type Collection to accomodate for additional paramters.

William
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How does the caller of the calculate method decide which parameters to pass?
 
Marco K Paul
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Basically, the user selected a calculation type from a dropdown on the screen and in my business object, I have a switch statement that figures out which type of concrete instance to create. since i am using a switch statement, i know which params to pass in. this doesn't sound right to me :roll:
 
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i'm no expert at all, so the following is just a guess:

as your methods have diferent signatures, i'd use an adapter Pattern to get them homogeneous; after that's done, i'd go for astrategy Pattern

hope this helps
 
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Marco K Paul:
Basically, the user selected a calculation type from a dropdown on the screen and in my business object, I have a switch statement that figures out which type of concrete instance to create. since i am using a switch statement, i know which params to pass in. this doesn't sound right to me :roll:



Having a Collection type as one of the parameters is not a good idea. Because your client code will end up with dependency on the method. This implicit dependency, such as - the client code knowing what types of parameter and number of arguments etc can be handled by the implementation.

You have to program to an interface. In your case I suggest you look at the additional parameters and use abstraction to see if you can create a data holder object (assuming they don't have any behavior).

Your current implementation is suffering from programming to the implementation. The business object is tightly coupled to the user interface. It is difficult to give you suggestions without looking at the requirements and the domain. Consider using a Mediator that decouples the user interface from the business objects. You could use just one Mediator class if that is good enough to encapsulate all the interaction between the UI and the business layer or you may need to customize the Mediator pattern to suit your needs.
 
Bartender
Posts: 1205
22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Marco K Paul:
Basically, the user selected a calculation type from a dropdown on the screen and in my business object, I have a switch statement that figures out which type of concrete instance to create. since i am using a switch statement, i know which params to pass in. this doesn't sound right to me :roll:



...and with good reason.

As william kane suggested, you could just pass the superset of parameters to the Calculate() method in each subclass, even if one or more may go unused. That way, once the client instantiates an object of the right class, it can just call Calculate() polymorphically.

Another possibility would be to pass in a reference to an object that would allow Calculate() to use getters to get any information they might need. This extra object might be just a Map or it might be some more specialized object. So let's say in the future you need to add a fifth possible ICalculateFees, which, unlike the previous four, needs to know the local county. The client would have to be modified to populate the Map with the county name (values.put("county", "Ashtabula")), but the other four ICalculateFees implementors could remain blissfully ignorant of the change.

Does that help?
[ June 22, 2005: Message edited by: Ryan McGuire ]
 
Marco K Paul
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Ryan McGuire:

Does that help?



Perfect, thx!


 
william kane
Ranch Hand
Posts: 260
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Ryan McGuire:


...and with good reason.

Just pass the superset of parameters to the Calculate() method in each subclass, even if one or more may go unused. That way, once the client instantiates an object of the right class, it can just call Calculate() polymorphically.

Another possibility would be to pass in a reference to an object that would allow Calculate() to use getters to get any information they might need. This extra object might be just a Map or it might be some more specialized object. So let's say in the future you need to add a fifth possible ICalculateFees, which, unlike the previous four, needs to know the local county. The client would have to be modified to populate the Map with the county name (values.put("county", "Ashtabula")), but the other four ICalculateFees implementors could remain blissfully ignorant of the change.

Does that help?


Ryan,
How do the approaches suggested by you differ from the one I have suggested


If the interface is used by a client program to pass parameters(Say user supplied input values) to the one of the 4 calculating algorithms then you could have the calculate method take 3 paramters in the interface, 2 of which are common to all the implementing classes and one of type Collection to accomodate for additional paramters


This approach is a mix of both of your approches as the interface exposes a calculate method that takes the mandatory params and allows for new params in the to be passed using the collection.
Thanks,
William
 
Ryan McGuire
Bartender
Posts: 1205
22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
My first paragraph IS a rehash of your solution. I had every intention of attributing that to you. I can't believe I missed that. Hold on while I go edit that. <MUZAK/>

I admit that my second approach is very close to what you suggested, but I figured the two differences...
  • Using a Map so that the access method is by name instead of position
  • Making the Map the only paramter so that access to the required data is homogeneous

  • was sufficient to warrent calling it new, or at least a non-trivial extension. I could have made those differences more clear.

    Ryan
    [ June 22, 2005: Message edited by: Ryan McGuire ]
     
    william kane
    Ranch Hand
    Posts: 260
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Ryan McGuire:
    My first paragraph IS a rehash of your solution. I had every intention of attributing that to you. I can't believe I missed that. Hold on while I go edit that. <MUZAK/>

    I admit that my second approach is very close to what you suggested, but I figured the two differences...

  • Using a Map so that the access method is by name instead of position
  • Making the Map the only paramter so that access to the required data is homogeneous

  • was sufficient to warrent calling it new, or at least a non-trivial extension. I could have made those differences more clear.

    Ryan

    [ June 22, 2005: Message edited by: Ryan McGuire ]

    Thanks Ryan,
    The intent of my query was to get to know the value add using a Map(as you have suggested) over a generic collection.
    Your clarification did the needful.
    Is there no other way to design for the unpredictable number of parameters with out having to use Maps or Collections.Just wondering...
    -William
     
    I would challenge you to a battle of wits, but I see you are unarmed - shakespear. Unarmed tiny ad:
    Smokeless wood heat with a rocket mass heater
    https://woodheat.net
    reply
      Bookmark Topic Watch Topic
    • New Topic