Sunteți pe pagina 1din 9

26/8/2014 Appendix C

http://www.ai-junkie.com/appendices/uml_class_diagrams.html 1/9
UML Class Diagrams
The Unified Modeling Language (UML) is a useful tool for object-oriented analysis and design.
One part of the UML, the class diagram, is especially good at clearly and succinctly describing the
static relationships between objects. Figure 1 shows the class diagram used to describe the
relationships between some of the objects used in one of the projects from the book Programming
Game AI by Example.
Figure 1. Example UML class diagram.
If this is the first time youve seen a UML class diagram youll probably find the figure perplexing,
but by the time youve finished reading this appendix it will make perfect sense. (Touch wood J)
Class Names, Attributes and Operations
First of all lets start off with the name, attributes and operations of a class. Classes are
represented by a rectangle divided into three compartments. The name of the class is given in bold
at the top of the rectangle, attributes are written beneath, and operations in the bottom
compartment. See Figure 2.
26/8/2014 Appendix C
http://www.ai-junkie.com/appendices/uml_class_diagrams.html 2/9
Figure 2. The class/object rectangle.
For example, if one of the objects in a game is a racing car it can be specified as shown in Figure
3.
Figure 3. Examples of attributes and operations
Of course, a racing car object is likely to be much more complex than this but we only need list the
attributes and operations of immediate interest. The class can easily be fleshed out more fully at a
later stage if necessary. (Quite often, I dont show any attributes or operations at all and use class
diagrams simply to show the relationships between objects, as demonstrated by Figure 1). Note
that the operations of a class define its interface.
The type of an attribute can be shown listed after its name separated by a colon. The return value
of an operation may also be shown in the same way, as can the type of a parameter. See Figure 4.
Figure 4. Specifying the type.
In my text I rarely use the name : type format for parameters as it often makes the diagrams too
large to fit on the page comfortably. Instead, I just list the type, or sometimes a descriptive name if
the type can be inferred from it.
Visibility of Attributes and Operations
Each class attribute and operation has a visibility associated with it. For instance an attribute may
either be public, private or protected. This property is shown using the symbols + for public, - for
private and # for protected. Figure 5 shows the racing car object with the visibility of its attributes
and operations listed.
Figure 5.
26/8/2014 Appendix C
http://www.ai-junkie.com/appendices/uml_class_diagrams.html 3/9
As with the types, its not imperative that you list the visibilities when drawing class diagrams, they
only need to be shown if they are immediately important to the part of the design you are modeling
(or, as in my case, describing).
When all the attributes, operations, types and visibilities etc are specified its very easy to convert
the class into code. For example, C++ code for the RacingCar object looks like this:
class RacingCar
{
private:

vector m_vPosition;

vector m_vVelocity;

public:

void Steer(float amount){...}

void Accelerate(float amount){...}

vector GetPosition()const{return m_vPosition;}
};
Relationships
Classes are not much use on their own. In object-oriented design each object usually has a
relationship with one or more other objects, such as the child parent type relationship of
inheritance, or the relationship between a class method and its parameters. The following pages
describe the notation the UML specifies to denote each particular type of relationship.
Association
An association between two classes represents a connection or link between instances of those
classes, and is denoted using a solid line. Unfortunately, at the time of writing, UML practitioners
seem unable to agree upon what the italicized text in the previous sentence actually means so I use
the assumption that an association is said to exist between two classes if one of them contains a
persistent reference to the other.
Figure 6 shows the association between a RacingCar object and a Driver object.
Figure 6. An association.
26/8/2014 Appendix C
http://www.ai-junkie.com/appendices/uml_class_diagrams.html 4/9
This class diagram tells us that a racing car is driven by a driver and that a driver drives a racing
car. It also tells us that a RacingCar instance maintains a persistent reference to a Driver instance
(via a pointer, instance or reference) and vice-versa. In this example both ends have been
explicitly named with a descriptive label called a role name, although much of the time this is not
necessary as the role is usually implicit given the names of the classes and the type of association
linking them. I prefer to only name the roles when I believe it is absolutely necessary as I feel it
makes a complex class diagram simpler to comprehend.
Multiplicity
The end of an association may also have multiplicity, which is an indication of the number of
instances participating in the relationship. For instance, a racing car can only have one or zero
drivers, and a driver is either driving a car or not. This can be shown as in Figure 7 using 0..1 to
specify the range.
Figure 7. An association showing multiplicity.
Figure 8 demonstrates how a RacingCar object can be shown to be associated with any number
of Sponsor objects (using an asterisk to indicate infinity as the upper bound of the range), and how
a Sponsor can only be associated with one RacingCar at any time.
Figure 8.
Figure 8 shows the long-hand way of specifying an unlimited range and a range of 1 but often (and
26/8/2014 Appendix C
http://www.ai-junkie.com/appendices/uml_class_diagrams.html 5/9
certainly within any text I write) you will see these relationships expressed in short-hand as shown in
Figure 9. The single asterisk denotes an unbounded range between 0 and infinity and the absence
of any numbers or an asterisk at the end of an association infers a singular relationship.
Figure 9.
It is also possible for a multiplicity to represent a combination of discrete values. For instance, a
car may have two or four doors -- 2, 4.
Given only the associations shown in Figure 9 we can infer how an interface for a RacingCar class
might look:
class RacingCar
{
public:

Driver* GetDriver()const;
void SetDriver(Driver* pNewDriver);
bool isBeingDriven()const;

void AddSponsor(Sponsor* pSponsor);
void RemoveSponsor(Sponsor* pSponsor);
int GetNumSponsors()const;

...
};
Navigability
So far the associations youve seen have been bi-directional: a RacingCar knows about a Driver
instance, and that Driver instance knows about the RacingCar instance. A RacingCar knows about
each Sponsor instance and each Sponsor knows about the RacingCar. Often however, you will
need to express a uni-directional association. For example, its unlikely that a racing car need be
aware of the spectators watching it, but it is important that a spectator is aware of the car it is
watching. This is a one-way relationship and is expressed by adding an arrow to the appropriate
end of the association. See Figure 10.
26/8/2014 Appendix C
http://www.ai-junkie.com/appendices/uml_class_diagrams.html 6/9
Figure 10. A Spectator has a uni-directional association with a RacingCar.
Notice also how the figure clearly shows how a spectator may be watching any number of racing
cars.
Shared and Composite Aggregation
Aggregation is a special case of association and denotes the part of relationship. For instance an
arm is a part of a body. There are two types of aggregation: shared and composite. Shared
aggregation is when the parts can be shared between wholes and composite aggregation is when
the parts are owned by the whole.
For example, the mesh (3D polygon model) that describes the shape of a racing car and is
textured and rendered to a display can be shared by many racing cars. As a result this can be
represented as shared aggregation, which is denoted by a hollow diamond. See Figure 11.
Figure 11. The relationship between a Mesh and a RacingCar is shown as shared aggregation.
Note that shared aggregation implies that when a RacingCar is destroyed its Mesh is not
destroyed. (Also note how the diagram shows that a Mesh object knows nothing about a
RacingCar object).
Composite aggregation is a much stronger relationship and implies the parts live and die with the
whole. Sticking with our racing car example we could say that a chassis has this type of
26/8/2014 Appendix C
http://www.ai-junkie.com/appendices/uml_class_diagrams.html 7/9
relationship with a car. A chassis is wholly owned by a racing car and is destroyed when the car is
destroyed. This kind of relationship is denoted using a filled diamond as shown in Figure 12.
Figure 12. The relationship between a Chassis and a RacingCar is composite aggregation.
There is a very subtle difference between shared aggregation and association. For example in the
design discussed thus far the relationship between a Spectator and a RacingCar has been shown
as an association but as many different Spectators can watch the same car you might think its
okay to show the relationship as shared aggregation. However a spectator is not part of the whole
of a racing car and the relationship therefore is association not aggregation.
Generalization
Generalization is a way of describing the relationship between classes that have common
properties. With regards to C++ generalization describes the is a relationship of inheritance. For
example, a design might require that different types of racing car are sub-classed from RacingCar
to provide vehicles for specific kinds of races, such as rally, formula 1 or touring. This type of
relationship is shown using a hollow triangle on the base class end of the association as shown in
Figure 13.
Figure 13. Expressing the base derived class relationship.
26/8/2014 Appendix C
http://www.ai-junkie.com/appendices/uml_class_diagrams.html 8/9
Often in object-oriented design we use the concept of an abstract class to define an interface to be
implemented by any subclasses. This is described explicitly by the UML using italicized text for the
class name and for any of its abstract operations. Therefore, if RacingCar is to be implemented as
an abstract class with one pure virtual method Update, the relationship between it and other racing
cars is shown as in Figure 14.
Figure 14. Describing an abstract base class.
Note, some people prefer to make the relationship more explicit by adding {abstract} beneath the
class name or after any abstract operations name. This is shown in Figure 15.
Figure 15. Describing an abstract base class more explicitly.

Dependencies
Often you will find that a class depends on another for some reason, yet the relationship between
them is not an association (as defined by the UML). This occurs for all sorts of reasons. For
instance, if a method of class A takes a reference to class B as a parameter then A has a
dependency on B. Another good example of a dependency is when A sends a message to B via a
third party, which would be typical of a design incorporating event handling.
A dependency is shown using a dashed line with an arrow at one end, and can be optionally
qualified by a label. Figure 16 shows how a RacingCar has a dependency to a RaceTrack.
26/8/2014 Appendix C
http://www.ai-junkie.com/appendices/uml_class_diagrams.html 9/9
Figure 16. The dependency relationship.
Notes
Notes are an additional feature you can use to zoom in on specific features that need further
explanation in some way. For instance, I use notes to add pseudo code where necessary. A note
is depicted as a rectangle with a folded corner and has a dashed line connecting it to the area of
interest. Figure 17 shows how a note is used to show how the UpdatePhysics method of a
RacingCar iterates through its four wheels, calling each ones Update method.
Figure 17. A note can be used to provide further detail.
Summing Up
Did you follow all that okay? To test yourself flick back to Figure 1 and see how much sense it
makes. If you still find it confusing, read through this appendix again. If you understood it, well done!
Now you can get back to the AI!

S-ar putea să vă placă și