Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design pattern selection dilemma

Controller receives a List of several Fruits from user. Controller needs to make juice from each of these fruits. One Juicer can make juice out of orange and grapefruit; another Juicer knows to make juice from apple, banana and papaya; and so on. Every Juicer can accept multiple Fruits in one go, it will process only the Fruits it's capable of and ignore other Fruits untouched. Kindly suggest an appropriate design for this problem. I have been considering the following options:

  1. Controller calls MasterJuicer.juice(List<Fruit> fruits). MasterJuicer in turn calls CitrusJuicer.juice(fruits) and PulpyJuicer.juice(fruits).
  2. Chain of Responsibility does not seem right. Order in which Juicers are called does not matter.
  3. Factory? Controller calls JuicerFactory.getJuicers(List<Fruit> fruits) to get a List<Juicer>. Controller then loops thru each Juicer and calls Juicer.juice(fruits). Is it common for a Factory to return a List of instances?
  4. Maintain a registry of Fruit vs. Juicer in a Map? Controller calls FruitsRegistry.getJuicer(Fruit fruit) for each fruit, then calls each Juicer in a loop.
like image 429
Somu Avatar asked May 28 '13 09:05

Somu


3 Answers

A factory can provide the correct juicers, but then your juicer handling logic is pushed to your controller.

A combination of the composite and visitor patterns might be useful to you.

  1. The composite pattern will allow you to construct a MasterJuicer that knows about the other juicers and can initiate the "juicing process" by delegating to the juicers. This handles the "structural" aspect of your problem.
  2. The visitor pattern allows each juicer to have a uniform method for interacting with them without the caller (the composite MasterJuicer) caring about how they work together. This handles the "behavioural" aspect.

You can pass a list of ingredients for processing between each visitor so they can interact with the fruits that they are concerned with.

If you don't want to register your juicers with the MasterJuicer manually, you might want to get clever with some kind of service discovery. A common technique in Java is to use annotations and classpath scanning to find the classes at runtime and register them automatically on start-up. There are a few libraries available that do this, or if you are already using the Spring Framework you can use its built-in scanning tools.

like image 144
seanhodges Avatar answered Nov 14 '22 09:11

seanhodges


I think the third option is the most appropriate, though the factory should be responsible for returning the appropriate juicer for the task - so it should not return all the juicers but the one you need for the task. The Map can be included in it for helping the right choice.

This case the factory contains the logic for choosing the right juicer, not the controller.

like image 2
ragklaat Avatar answered Nov 14 '22 09:11

ragklaat


In my opinion the pattern your looking for is the Chain of Responsibility

http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern

regards

like image 2
Andrea Sindico Avatar answered Nov 14 '22 08:11

Andrea Sindico