• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

when to subclass

 
william kane
Ranch Hand
Posts: 260
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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 ]
 
Mark Spritzler
ranger
Sheriff
Posts: 17278
6
IntelliJ IDE Mac Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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 ]
 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Ryan McGuire
Ranch Hand
Posts: 1068
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 260
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 1068
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 1068
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ryan, you had some really good tips on when Decorator does or does not apply. We oughtta capture those somewhere!
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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 !
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic