0

I'm looking for the correct design pattern to decouple some of the logic on some abstract classes I've got. First we have a base class Fruit and child classes apple, orange, and mango. Then I have some classes that perform some logic on the fruit. These classes are the chopping, cooking, and peeling classes. Now much of the logic for chopping is identical for each fruit, as well as cooking and peeling, however there is some specific differences that occur for each type of fruit in all the working classes. I don't particularly want to give the fruit classes a lot of information about what it takes to chop, cook, or peel since that logic is quite complicated, yet I'm not fond of the chop/cook/peel class having so much code related to specific fruits.

So to sum it all up which design pattern correctly models said pattern of fruits and actions on fruits. Thank you for all input.

Medran
  • 43
  • 2
  • 2
    There is rarely _correct_ design patterns, and inheriting from Fruit seems to have little value. – Telastyn Sep 21 '16 at 02:51
  • 4
    Why are there chop/cook/peel class(es)? Action/verbs should be modeled as methods, whereas nouns as base classes when more abstract or subclasses when more concrete. – Erik Eidt Sep 21 '16 at 03:02
  • 2
    Simply naming them Chopper, Cookpot, and Peeler can take care of that. – candied_orange Sep 21 '16 at 03:15
  • @CandiedOrange Is that a joke? The problem is not a missing *-er* at the end of a word. The design of the class structure is the problem. Using agent nouns for class names is simply an indicator for such a fundamental flaw. – gardenhead Sep 21 '16 at 03:21
  • Hmm, nobody argues with the utility of a *Sorter.* – Robert Harvey Sep 21 '16 at 03:23
  • 2
    Nope, not a joke. Chopper, Cookpot, and Peeler are behavior objects while Apple, Orange, and Mango are value objects. – candied_orange Sep 21 '16 at 03:24
  • 1
    @RobertHarvey Um, I do. What language uses a Sorter? None that I use. – gardenhead Sep 21 '16 at 03:24
  • 1
    https://www.google.com/search?q=sorter+class – Robert Harvey Sep 21 '16 at 03:26
  • That doesn't mean they're a good idea or should exist. Can you point me to a specific class in a specific language? I'm wondering what the utility of such a class would be – gardenhead Sep 21 '16 at 03:32
  • 1
    Possible duplicate of [Choosing the right Design Pattern](http://programmers.stackexchange.com/questions/227868/choosing-the-right-design-pattern) – gnat Sep 21 '16 at 06:17
  • 1
    This sort of question definitely supports the trendy new idea that coding to design patterns is itself, an anti-pattern. What you need is a solution that maximises DRY, minimised coupling and goes nowhere near inheritance. Who cares what "design pattern" that might involve. – David Arno Sep 21 '16 at 09:00
  • Sorting templates in STL C++ are an example of this all the logic of sorting is handled in the algorithm, all the class needs to do is provide a comparitor. It would make no sense for each value class to have the sorting algorithm included as a method. I suppose the thing that breaks this in my class is that the action required cannot be universally implemented in the value class the way a comparitor can. – Medran Sep 21 '16 at 16:03
  • The answer from choosing the right design pattern isn't quite what I'm looking for. As its a bit of a non answer talking about not developing based off pattern. – Medran Sep 21 '16 at 21:18

2 Answers2

4

This is actually a general conundrum known as the expression problem.

The gist is this: you have some types, and you have some functions that act on those types, and you need to specify the action of each function on each type. Conceptually, you may think of a two-dimensional table where the rows are labeled by types and the columns by functions. The cell (i, j) specifies the behavior of function j on type i.

Thus, if we just view a row of this table, we get all the functions acting on a specific type, which is more or less an object. If we instead take a column-oriented view, we get a single function acting on all the different types, which is function by case analysis. Neither of the two views is unilaterally superior, so I will cover them both.

Object-oriented (row-based) approach

Create an abstract base class Fruit with methods slice, cut, peel, etc. Create classes Pear, Apple, etc that inherit from Fruit. The shared logic goes in the base class, the specific logic in the subclasses.

Note that most programmers (including myself) consider inheritance bad practice. It is better to make Fruit an interface that the other classes implement. For code reuse, use composition (that is, create a function which does what you want and use it in each class).

Functional (column-oriented) approach

Create a sum type Fruit with injections Apple, Pear, etc. Create functions slice, cut, that case on the instance type of their argument, e.g.

fun slice (fruit: Fruit) = case fruit of Pear -> ... | Apple -> ...

There are of course other approaches (e.g. using modules and signatures), but these are two of the common ones.

gardenhead
  • 4,719
  • 2
  • 19
  • 24
  • 1
    Most programmers consider OOP bad practice? – Ewan Sep 21 '16 at 11:54
  • @Ewan I said "inheritance", not OOP. Many *do* consider OOP substandard, but even those who favor it (which is still the majority of programmers from what I can tell), advise composition over inheritance. – gardenhead Sep 21 '16 at 14:12
  • I'm not sure that a single layer of inheritance would be considered bad practice. but hey, all we know is apples and pears and slicers etc – Ewan Sep 21 '16 at 14:21
1

You're asking for a design pattern to implement double dispatch. The logic for performing an action on a fruit depends on both the type of action, and the type of fruit.

I can't give a more specific answer because fruits and cooking actions are not real OOP objects. The appropriate design pattern to use will depend on what your objects really are.

Tanner Swett
  • 1,359
  • 8
  • 15
  • Lots of interesting articles about double dispatch here is one suggesting its not a good pattern in general https://lostechies.com/derekgreer/2010/04/19/double-dispatch-is-a-code-smell/ – Medran Sep 21 '16 at 21:19
  • more interesting reading in the related visitor pattern https://sourcemaking.com/design_patterns/visitor – Medran Sep 21 '16 at 21:23