aspose file tools*
The moose likes Java in General and the fly likes Need advice on a simple design Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Need advice on a simple design" Watch "Need advice on a simple design" New topic
Author

Need advice on a simple design

Unnar Björnsson
Ranch Hand

Joined: Apr 30, 2005
Posts: 164
Hello ranchers I have often encountered the following dilemma while programming and I would like to get your opinion on this.
Lets take for example a class called Food which has some extending children like Vegetable and Fruit
Vegetable has some children like Carrot and Cabbage
Fruit also has some children, for example Orange and Apple
Just a simple 3 layer inheritance structure. Now what I want to ask is if you have an array of type Food and you want to find all the fruits in the array, for instance loop through the array and print out "A fruit!" if that object is a Fruit
You would have to ask each object what kind of food it is, and the question is: What is the best way of getting this info?

I know there are a lot of ways to do this, the one I have usually preferred is using this design:


And then in the main class:


I've read that this is not a good practice, you should use enums instead, but I really don't like enums for some reason. You could also use instanceof operator to achieve this but I've also read that using instanceof in this way is a bad practice too.
What is the best practice here? How would you do this?>
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3649
    
  17

Definitely not int constants. Enums *are* preferable. You should really learn to appreciate them.

In this particular case, I would use the instanceof operator. However, in any serious application I would question why you have an array of Food in the first place, when you only need Fruits.
Wendy Gibbons
Bartender

Joined: Oct 21, 2008
Posts: 1107

I can easily see why he would want to operate on only some of the items in a list.
and i dislike instance of (isn't it a code smell?), but vote for enum instead
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8248
    
  23

Wendy Gibbons wrote:I can easily see why he would want to operate on only some of the items in a list.
and i dislike instance of (isn't it a code smell?), but vote for enum instead

I have to disagree; in this case, the attribute is simply duplicating the behaviour of instanceof, so I'd get rid of it completely.

For some other type of categorization, I would definitely agree with Stephan that enums are the way to go.

Winston


Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Brian Burress
Ranch Hand

Joined: Jun 30, 2003
Posts: 122
I'll chime in to support instance of as well. If all of the valid implementations of Food have to be defined in food then you will have a very tightly coupled solution. It may not be a requirement for your example, but in the spirit of OO discussion, what if a third party wants to implement a "Meat" class inheriting from Food. How will the Food enum be updated to support it?

The enum approach is only going to let you support "one layer" of abtraction. The base layer of course is Food itself and the second layer in the example is Fruit or Vegetable.

In the enum example, how would you further distinguish Orange and Apple? They are both valid fruit and instance of would not allow Fruit to be determined but also instance of Apple or Orange. The enum approach would not support this capability.


Wendy Gibbons
Bartender

Joined: Oct 21, 2008
Posts: 1107

Brian Burress wrote:I'll chime in to support instance of as well. If all of the valid implementations of Food have to be defined in food then you will have a very tightly coupled solution. It may not be a requirement for your example, but in the spirit of OO discussion, what if a third party wants to implement a "Meat" class inheriting from Food. How will the Food enum be updated to support it?

The enum approach is only going to let you support "one layer" of abtraction. The base layer of course is Food itself and the second layer in the example is Fruit or Vegetable.

In the enum example, how would you further distinguish Orange and Apple? They are both valid fruit and instance of would not allow Fruit to be determined but also instance of Apple or Orange. The enum approach would not support this capability.




good point, could you make the classes visitable?
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8248
    
  23

Wendy Gibbons wrote:good point, could you make the classes visitable?

Ooof. Over-engineering perhaps?

Winston
Brian Burress
Ranch Hand

Joined: Jun 30, 2003
Posts: 122
I have not used the visitor pattern myself to have practical experience with it. Quickly reviewing the def of the pattern here, I am not sure if it would be applicable when you are trying to get some sort of result or status back for a specific instance of an object as the focus seems to be more for performing operations across. I am not immediately seeing an aspect in the visitor examples that would support this. You could have various 'visit' methods accepting an object as Fruit or Vegetable, but then we go back to the point of distinguising between Orange, Apple, etc.

Possibly one of the better responses to the original posting would be to ask for more requirements on what the solution is trying to accomplish. Depending on the problem statement, the rest of the posts help portray possible approaches.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3649
    
  17

Well obviously the problem lies in that we have a foodBasket to begin with, instead of a fruitBasket. Where did the basket come from? Wasn't there a way to get one with just fruits?

The solutions offered here are ways to deal with a problem that shouldn't be there in the first place.
Wendy Gibbons
Bartender

Joined: Oct 21, 2008
Posts: 1107

Stephan van Hulst wrote:Well obviously the problem lies in that we have a foodBasket to begin with, instead of a fruitBasket. Where did the basket come from? Wasn't there a way to get one with just fruits?

The solutions offered here are ways to deal with a problem that shouldn't be there in the first place.


That is true, but after joining a company with 10 years of legacy code, lots of it is generated, problems that shouldn't be there, often are.
Unnar Björnsson
Ranch Hand

Joined: Apr 30, 2005
Posts: 164
You seem to agree that the foodBasket should be fruitBasket, ok but if I want to make an inventory of food available at the store? The easiest way would be to use one Arraylist<Food>() which has the same problem as foodBasket, so would you split the inventory into multiple arraylists for each category then?
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8248
    
  23

Unnar Björnsson wrote:You seem to agree that the foodBasket should be fruitBasket, ok but if I want to make an inventory of food available at the store? The easiest way would be to use one Arraylist<Food>() which has the same problem as foodBasket, so would you split the inventory into multiple arraylists for each category then?

No, but I think I might have some sort of Inventory hierarchy that mirrors my Food one. That way, you can just update relevant totals whenever you add or remove items from your stock. I suspect there might even be a way of doing it with your existing classes, but I'm afraid my brain's a bit tired at the moment. If I think of something tomorrow, I'll post it.

Winston
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Need advice on a simple design