Reputation: 172
I was wondering if I can model the relationship between the two class hierarchies below, in the way that I did:
The code that would represent the meaning of this would be something like:
public abstract class Car
{
protected Engine engine;
}
public class StreetCar extends Car
{
public StreetCar()
{
engine = new StreetEngine();
}
}
...and similarly for the class OffroadCar, it would do something like engine = new OffroadEngine()
. I have not included anything about the accelerate() method, it's not relevant.
I just want to know if the composition is modeled correctly or if it's redundant or even wrong to add that many composition arrows.
Upvotes: 5
Views: 6782
Reputation: 4143
Before answer question, this is one of those cases, where is a good idea to split hierarchy relationships from composition relationships, as if they where different kind of diagrams.
Note: I added Engine to the diagram, as "protected", and "Class" prefix, to avoid confusing.
(1) Composition Diagram
An object of "CarClass" its composed by 1 single object of "EngineClass".
..............................................................................
..+-------------------------------------+........+-------------------------+..
..| <<abstract>> |........| <<abstract>> |..
..| CarClass |........| EngineClass |..
..+-------------------------------------+........+-------------------------+..
..| [#] Engine: EngineClass |<*>-----+ [+] startEngine(): void |..
..+-------------------------------------+........+-------------------------+..
..| [+] acelerate(): void <<virtual>> |.....................................
..+-------------------------------------+.....................................
..............................................................................
(2.1) Inheritance Diagram
An object of "CarClass" may have child classes, upon certain scenario.
...........................................
..+-------------------------------------+..
..| <<abstract>> |..
..| CarClass |..
..+-------------------------------------+..
..| [#] Engine: EngineClass |..
..+-------------------------------------+..
..| [+] acelerate(): void <<override>> |..
..+-----------------+-------------------+..
.................../.\.....................
................../...\....................
.................+--+--+..............................................................
....................|.................................................................
....................+------------------------------------------+......................
....................|..........................................|......................
..+-----------------+-------------------+....+-----------------+-------------------+..
..| <<concrete>> |....| <<concrete>> |..
..| StreetCarClass |....| OffRoadCarClass |..
..+-------------------------------------+....+-------------------------------------+..
..| [+] acelerate(): void <<override>> |....| [+] acelerate(): void <<override>> |..
..+-------------------------------------+....+-------------------------------------+..
......................................................................................
(2.2) Inheritance Diagram
An object of "EngineClass" may have child classes, upon certain scenario.
...........................................
..+-------------------------------------+..
..| <<abstract>> |..
..| EngineClass |..
..+-------------------------------------+..
..| [+] acelerate(): void <<override>> |..
..+-----------------+-------------------+..
.................../.\.....................
................../...\....................
.................+--+--+..............................................................
....................+------------------------------------------+......................
....................|..........................................|......................
....................|..........................................|......................
..+-----------------+-------------------+....+-----------------+-------------------+..
..| <<concrete>> |....| <<concrete>> |..
..| StreetEngineClass |....| OffRoadEngineClass |..
..+-------------------------------------+....+-------------------------------------+..
..| [+] startEngine(): void <<override>>|....| [+] startEngine(): void<<override>> |..
..+-------------------------------------+....+-------------------------------------+..
......................................................................................
3 Answer
Now, this is a case, where a class has an unleast one composing member, and its type may be overriden, when the main class its overriden. This is sometimes called the "Paralell Hierarchy Software Pattern" or "Dual Hierarchy Software Pattern".
You have only mention 2 subclasses of each main class, but, in reality, there could be more.
Usually I make charts like this 2 ways. One, I make the first diagram, adding a comment, that indicates that its this case.
3.1 Main Paralell Hierarchy Diagram
..............................................................................
..+-------------------------------------+........+-------------------------+..
..| <<abstract>> |........| <<abstract>> |..
..| CarClass |........| EngineClass |..
..+-------------------------------------+........+-------------------------+..
..| [#] Engine: EngineClass |<*>-----+ [+] startEngine(): void |..
..+-------------------------------------+........+------------+------------+..
..| [+] acelerate(): void <<virtual>> |.....................|...............
..+--------------+----------------------+.....................|...............
.................|............................................|...............
.................+--------------------------------------------+...............
.................|............................................................
........+--------+-------+....................................................
........| Note: |....................................................
........| Paralell /....................................................
........| Hierarchy /| ...................................................
........| / |....................................................
........+-------------/--+....................................................
..............................................................................
The second case, its when both classes has child classes that both add members.
3.2 Additional Paralell Hierarchy Diagram
..............................................................................
..+---------------------------------------+........+-------------------------+..
..| <<concrete>> |........| <<concrete>> |..
..| OffRoadCarClass |........| OffRoadEngineClass |..
..+---------------------------------------+........+-------------------------+..
..| [+] createEngine(): void <<override>> |<*>-----+ [+] startEngine(): void |..
..+---------------------------------------+........| [+] nitroLevel(): void |..
..| [+] useNitro(): void |........+------------+------------+..
..| [+] acelerate(): void <<override>> |.....................|...............
..+--------------+------------------------+.....................|...............
.................|..............................................|...............
.................+----------------------------------------------+...............
.................|............................................................
........+--------+-------+....................................................
........| Note: |....................................................
........| Paralell /....................................................
........| Hierarchy /| ...................................................
........| / |....................................................
........+-------------/--+....................................................
..............................................................................
I may add additional diagrams, if necesarilly.
4 Show me the code
In order, to manage this "parallel" hierarchies, usually, the creation of the composite members its managed by a overriden method.
public abstract class EngineClass
{
public void startEngine() { ... }
} // EngineClass
public abstract class CarClass
{
protected EngineClass engine;
public CarClass()
{
// ...
}
public EngineClass createEngine()
{
EngineClass Result = new EngineClass();
return Result;
}
public void start()
{
this.Engine = createEngine();
}
} // CarClass
public class StreetCarClass extends CarClass
{
public StreetCarClass()
{
// ...
}
@override
public EngineClass createEngine()
{
EngineClass Result = new StreetCarEngineClass();
return Result;
}
} // StreetCarClass
public class OffRoadCarClass extends CarClass
{
public OffRoadCarClass()
{
// ...
}
@override
public EngineClass createEngine()
{
EngineClass Result = new OffRoadCarEngineClass();
return Result;
}
} // OffRoadCarClass
public class ExampleClass
{
public static main()
{
EngineClass OffRoadCar = new OffRoadCarClass();
OffRoadCar.start();
}
} // OffRoadCarClass
Cheers.
P.S. Can I, ur, haz a Fishburguer ?
Upvotes: 3