OO Solution

Car > VW > Golf > ....

Suppose we got that hierarchy where all cars provide services as startEngine(), stopEngine(), etc.

On the other side a VW Golf can be automatic, can be convertible, etc. and should provice services as openRoof in case of convertible or should startEngine different in case automatic

I don't think creating a class for each of those features (automatic, convertible, etc) would be the correct way.

How would you implement this trying to get the best OO design for this.

Maybe booleans of the form "isConvertible" "isAutomatic", maybe interfaces for asking instanceof although I think using instanceof should be avoid in OO.

Regards.

[708 byte] By [jfreebsda] at [2007-10-2 23:56:31]
# 1

You have two options (which are not mutually exclusive). You can define interfaces such as AllowsConvertible, AllowsTransmissionSelection, etc. Then, each implementing class can easily define whether that interface is applicable to it. Another option is to use the GoF design pattern "Decorator".

- Saish

Saisha at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...
# 2
"Decorator" - a fine choice.Look at the java.io package for examples. Subclasses of InputStream subclasses are Decorators.%
duffymoa at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

I think the issue with decorator is that it is not interactable. If you had automatic vs. manual transmission that did not require user input, then it would work. But since you have to expose either a stick shift or a auto-gear shift, it wouldn't work.

I also dont think VW or Golf qualify as 'types'. This is the make and model which are properties of the car class and not classes themselves.

I'd use interfaces to add the new functionality. You can put the interfaces on the car class or expose them through a method of the car class.

_dnoyeBa at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...
# 4
I think both methods will work (decorator or additional interfaces). And I do agree that VW and Golf are not really types. They are instances of a more generic type. But I do believe both options are valid. :^)- Saish
Saisha at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

I've seen it. It look like a Proxy that contains the reference to the object, provides all reference services, and the difference is that the decorator extends from the reference superclass.

This maybe could be a fine solution, maybe not.

Suppose the VW Golf is convertible. Due to we don't a huge car hierarchy we do not create the GolfConvertible subclass, instead of that we would create a ConvertibleDecorator at Golf hierarchy level and allow this ConvertibleDecorator to keep a reference to a Golf instance and provide its methods obviously.

Now what if I instance a ConvertibleGolf and wants to open the roof ( openRoof() ) ?

I would have to do..

Car car = new ConvertibleGolf();

((ConvertibleGolf) car).openRoof();

That does not seem to be a fine solution, maybe I misunderstood what you told me to do.

Regards.

jfreebsda at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

Yes, thats exactly the solution I suggest. it looks like a fine solution to me. Maybe your code is a bit oversimplistic since you need to check if the interface is implemented first.

I also suggested that instead of putting the interface on the car class, that you offer a method that would expose other interfaces. Perhaps like

class Car {

public Object getFacility(Class type) {

if(type == ConvertibleTop.class){

return this.convertibleHandler;

}

else if(type == ...){

//etc...

}

else {

return null;

}

}

}

Car car = new Car("VW","Golf");

ConvertibleTop t = (ConvertibleTop )car.getFacility(ConvertibleTop.class);

if(t != null){

t.openRoof();

}

I think this is a bit more clean that putting the interface on the car. Its more extensible. However, clearly its less type safe.

Adding the convertible top ability to the particular car can be done at compile time with a new class or some options on the constructor, or a static factory method. Or at runtime using a similar method like createFacility.

I see now how Decorator would work. With Decorator you need to define all your methods on car by default but have them do nothing.

The Decorator pattern has built into it an assumption that all cars do the same things just in different ways. So you would have to change the convertible top interface into a general Top interface and its methods into something that applied to hard tops and regular tops.

If that is your assumption, then It should work nicely. Otherwise, it won't be so elegant.

_dnoyeBa at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...
# 7

> I see now how Decorator would work. With Decorator you need to define all your methods on car by default but have them do nothing. The Decorator pattern has built into it an assumption that all cars do the same things just in different ways.

That's not the way I understand it. From the GoF:

Decorator (175) Attach additional responsibilities to an object dynamically.

Applied to this example, a ConvertibleDecorator would add the convertible functionality to an existing car.

~

yawmarka at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...
# 8

I don't think creating a class for each of those features (automatic, convertible, etc) would be the correct way.

I'm just thinking out loud here, but I'm not sure there's a correct way when discussing academic examples like this outside the context of an actual application. Where one pattern might seem to solve one issue in a theoretical sense, a different approach might make more sense given an actual set of requirements.

That said, I'm certain there are definitely wrong ways, but no "One True Way"?at this level of discussion.

Just some ramblings... :o)

~

yawmarka at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...
# 9

@DynoeB: The getFacility() method troubles me just a bit. I think it's fine for a Builder or Factory type usage. However, whenever I see lot's of if statements nested together like that (especially when comparing classes), I think there is probably a better polymorphic solution, normally an interface.

Just my two cents. Though I agree with Yawmark, without a few more requirements to go on, a lot of designs could be valid.

- Saish

Saisha at 2007-7-14 16:43:09 > top of Java-index,Other Topics,Patterns & OO Design...