aspose file tools*
The moose likes OO, Patterns, UML and Refactoring and the fly likes when to subclass Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "when to subclass " Watch "when to subclass " New topic
Author

when to subclass

william kane
Ranch Hand

Joined: Nov 21, 2000
Posts: 260
Hi,
I need some clarity on choosing between a subclass or instance when dealing with classes that have values of instance variable driving some behaviour.
Consider this
Car dealer has a system that reports daily sales.
Cars can be of different types like air conditioned,non-ariconditioned,with stereo,without stereo etc.
Diffent combinations of the same are possible.
Cars can also be categorized under high end,low end, mid range.
All cars must belong to any one of these categories.

The cost of the cars varies based on the combination of types and also based on the categories.

My question is if its a good design to have category as a variable in the Car class and let the getCost method return the cost based on the category using conditional logic.
OR
Should i use sub classes for category to accomodate of future categories.
Thanks in advance
William


Help me!Help you!!!
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
See if the Decorator chapter in Head First Design Patterns looks just like your "options" problem. The "category" problem might have a different solution.
[ June 09, 2005: Message edited by: Stan James ]

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17257
    
    6

Singing,

"The Developer" from Kenny Rogers.


You got to know when to subclass, know when to refactor.
Know when to synchronize, know when to create a runnable.
You never implement an interface while their still writing the requirements.
There be time enough for implementing when the detail design is done.


Thank you, I have shows at 7 and 11PM.

Mark
[ June 09, 2005: Message edited by: Mark Spritzler ]

Perfect World Programming, LLC - Two Laptop Bag - Tube Organizer
How to Ask Questions the Smart Way FAQ
Layne Lund
Ranch Hand

Joined: Dec 06, 2001
Posts: 3061
Originally posted by Mark Spritzler:
Singing,

"The Developer" from Kenny Rogers.


You got to know when to subclass, know when to refactor.
Know when to synchronize, know when to create a runnable.
You never implement an interface while their still writing the requirements.
There be time enough for implementing when the detail design is done.


Thank you, I have shows at 7 and 11PM.

Mark

[ June 09, 2005: Message edited by: Mark Spritzler ]


ROFLMAO! That's awesome. I truely wish I had such creative ability.


Java API Documentation
The Java Tutorial
Ryan McGuire
Ranch Hand

Joined: Feb 18, 2005
Posts: 1010
    
    3
I agree with Stan that this sounds like a job for the Decorator pattern. We discussed it recently in this thread.

When is the Decorator pattern good?
When a given target object (Car in your case) could have some number of options, but the number of possible combinations (LowEnd, no A/C, with stereo) would make the class hierarchy explode horizontally. It also makes adding future options easier; each one would just be another Decorator. Of course, future maintainability is the driving force behind many of the design patterns.

BUT...
If every Car is going to have some value for each option (each either does or doesn't have air conditioning) and any value might add some specific functionality, then implementing Decorators doesn't save much. Also, if the number of options is never going to change (you're positive A/C, stereo, class, etc. are all you'll ever care about), then you might just as well just implment everything in one class.

However, to answer your explicit question...
I would make a single Car class that has boolean hasAC, boolean hasStereo, String luxuryLevel, etc. instead a set of 12 ACStereoHighEnd NoACStereoHighEnd, ACNoStereoHighEnd, ... classes. Instantiation would be alot easier. Compare the two following chunks of code:



This makes sense especially since it sounds like all your program has to do is make reports. It would be just as easy to loop through a bunch of Car objects and check the value of the fields as would be to check their classes or implmented interfaces or their subclasses field value.

Ryan
william kane
Ranch Hand

Joined: Nov 21, 2000
Posts: 260
Originally posted by Ryan McGuire:
I agree with Stan that this sounds like a job for the Decorator pattern. We discussed it recently in this thread.

When is the Decorator pattern good?
When a given target object (Car in your case) could have some number of options, but the number of possible combinations (LowEnd, no A/C, with stereo) would make the class hierarchy explode horizontally. It also makes adding future options easier; each one would just be another Decorator. Of course, future maintainability is the driving force behind many of the design patterns.

BUT...
If every Car is going to have some value for each option (each either does or doesn't have air conditioning) and any value might add some specific functionality, then implementing Decorators doesn't save much. Also, if the number of options is never going to change (you're positive A/C, stereo, class, etc. are all you'll ever care about), then you might just as well just implment everything in one class.

However, to answer your explicit question...
I would make a single Car class that has boolean hasAC, boolean hasStereo, String luxuryLevel, etc. instead a set of 12 ACStereoHighEnd NoACStereoHighEnd, ACNoStereoHighEnd, ... classes. Instantiation would be alot easier. Compare the two following chunks of code:



This makes sense especially since it sounds like all your program has to do is make reports. It would be just as easy to loop through a bunch of Car objects and check the value of the fields as would be to check their classes or implmented interfaces or their subclasses field value.

Ryan


Thanks Ryan,
This is what I would infer from your reply
Option1:
Create a single Car class and use the values of the instance variables to determine the cost of the car.This implementation would therefore have if else statements in the getCost method that would compute the cost of the Car object based on the values of the instance variables.
Option2:
Have Classes for each combination and have getCost overridden in all subclasses.We would still end up having a chuck of conditional statement but this time to determine the class to instantiate.

But what about using the decorator pattern assuming that new combinations are inevitable in the market.
How will it be be use decorators for stereo,no stereo etc and have a conditional getCost in each of the decorators to have the cost calculated based it being highend,mid range and low end?

Is there a way to accomodate for more categories that are likely to come up in the future say mid range plus etc?So that i dont end up having to modify all the getCost method in all the decorators to have one more else if statement.
Thanks again,
William
Ryan McGuire
Ranch Hand

Joined: Feb 18, 2005
Posts: 1010
    
    3
Originally posted by william kane:

This is what I would infer from your reply
Option1:
...

Option2:
Have Classes for each combination and have getCost overridden in all subclasses.We would still end up having a chuck of conditional statement but this time to determine the class to instantiate.


Close. Yes getCost() would be overridden in each subclass. However, there wouldn't be any need for conditionals, because you could hardcode the value getCost() in each class returned:



But what about using the decorator pattern assuming that new combinations are inevitable in the market.
How will it be be use decorators for stereo,no stereo etc and have a conditional getCost in each of the decorators to have the cost calculated based it being highend,mid range and low end?


The Stereo and NoStereo Decorators wouldn't reference the High/Mid/Low information, but just the additional cost incurred by having a stereo.



On the other hand, WithoutStereoDecorator.getCost() might just return target.getCost() without any additional cost.

You might define a single Decorator class to handle all the High/Mid/Low possiblities:




Is there a way to accomodate for more categories that are likely to come up in the future say mid range plus etc?So that i dont end up having to modify all the getCost method in all the decorators to have one more else if statement?


Sure, just make more Decorator classes.

But watch out...
The Decorator pattern DOESN'T apply when there is interaction between the options. Let's say a plain car costs $10,000, one with A/C costs $12,000, one with a stereo costs $13,000, and one with A/C and a stereo costs $15,500. In that case the additional functionality of the separate Decorators are NOT independent. This breaks the pattern.

Ryan
Ryan McGuire
Ranch Hand

Joined: Feb 18, 2005
Posts: 1010
    
    3
Originally posted by Ryan McGuire:


Originally posted by william kane:
Option2:
Have Classes for each combination and have getCost overridden in all subclasses.We would still end up having a chuck of conditional statement but this time to determine the class to instantiate.

Close. Yes getCost() would be overridden in each subclass. However, there wouldn't be any need for conditionals, because you could hardcode the value getCost() in each class returned:


Oops, I misread your Option 2. I should have just said, "Yes, exactly."

I hope I didn't cause too much confusion.

Ryan
[ June 16, 2005: Message edited by: Ryan McGuire ]
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
Ryan, you had some really good tips on when Decorator does or does not apply. We oughtta capture those somewhere!
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Stan James:
Ryan, you had some really good tips on when Decorator does or does not apply. We oughtta capture those somewhere!


Don't hesitate to add them to http://faq.javaranch.com/view?DesignPatternFaq !


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: when to subclass