uml-basico-patrones

Basic UML for Understanding Pattern Diagrams

  • 5 min

A UML class diagram is a visual representation of the classes in a system and the relationships between them. If you open any book on design patterns (including the famous GoF), you’ll find plenty of these “boxes and arrows.”

Those boxes are UML (Unified Modeling Language) diagrams.

To follow this course, you don’t need to master UML or know how to create complex deployment or sequence diagrams. You do need to know how to read a class diagram.

Patterns are, in essence, structures of classes and their relationships. If we don’t understand what it means for an arrow to have a diamond tip or be dashed, we won’t understand the difference between an association and a composition, and therefore, we’ll implement the pattern incorrectly.

Let’s go over the UML survival kit for this course.

The Class

The basic unit in these diagrams is the Class. It is represented as a rectangle divided (usually) into three sections:

  • Class Name: for example, Customer or OrderFactory. If it appears in italics, it represents an abstract class.
  • Attributes: variables or data (state).
  • Methods: functions (behavior).

Additionally, you’ll see symbols in front of attributes and methods that indicate their visibility:

  • + Public: Accessible from anywhere.
  • - Private: Accessible only from within the class itself.
  • # Protected: Accessible from the class and its derivatives (inheritance).

In pattern diagrams, attributes are often omitted to simplify and focus only on the key methods that define the pattern.

The Relationships

This is where the real meat lies. The lines connecting the classes tell us how they interact with each other. Let’s look at the 5 most important ones for understanding patterns.

Inheritance

It represents the “Is a” relationship. It is drawn with a continuous line ending in a hollow triangle pointing to the parent class (superclass).

  • Meaning: The child class inherits attributes and methods from the parent.
  • C# Code: public class Dog : Animal { ... }

Implementation

It represents the “Fulfills the contract” relationship. It is used with Interfaces. It is drawn with a dashed line ending in a hollow triangle pointing to the interface.

  • Meaning: The concrete class implements the methods defined in the interface. This is key in patterns like Strategy or Observer.
  • C# Code: public class LogFile : ILogger { ... }

Association

This is the most generic relationship. It represents “Has a” or “Knows a”. It is drawn with a simple continuous line (sometimes with an open arrow at the end to indicate navigability).

  • Meaning: One class holds a reference to another class as an attribute.
  • Example: A User object has a property of type Address.

Aggregation and Composition

This is where many people get confused. Both are types of Association, but with important nuances regarding the lifecycle of the objects.

Aggregation (white diamond ◇)

Represents a “weak” relationship. The “whole” object has “part” objects, but the parts can live independently.

  • Symbol: Continuous line with a hollow (white) diamond at the container’s end.
  • Example: A football Team and its Players. If the team disappears, the players continue to exist (they can go to another team).
  • In C++: Usually a pointer (Player*) or a reference that we don’t delete in the destructor.

Composition (black diamond ◆)

Represents a “strong” relationship. The “whole” object is the absolute owner of the “parts”. If the container dies, the parts die with it.

  • Symbol: Continuous line with a filled (black) diamond at the container’s end.
  • Example: A House and its Rooms. If you destroy the house, the rooms cease to exist. A “loose” room without a house makes no sense.
  • In C++: An object by value, or a std::unique_ptr that is deleted in the destructor.

Dependency

Represents a temporary or usage relationship. “Uses a”. It is drawn with a dashed line with an open arrow.

  • Meaning: One class uses another, but does not contain it as an attribute. This often occurs when a class receives another as a parameter in a method.
  • Example: A method Print(Document doc) in the Printer class. The printer “uses” the document to print it, but doesn’t “have” a document permanently.
  • Importance: If the Document class changes, the Printer class could be affected.

Visual Summary for Developers

To make it crystal clear, let’s translate it into pseudo-code, which is how we understand each other best:

RelationshipUML (arrow)ConceptMental Code
Inheritance───▷ (Continuous)“Is a”class B : A { }
Implementation- - ▷ (Dashed)“Fulfills contract”class B : InterfaceA { }
Composition◆─── (Black)“I create you and I destroy you”new Part() inside the Constructor
Aggregation◇─── (White)“I have you, but you are free”Receives Part from outside and stores it
Dependency- - -> (Arrow)“I use you for a moment”Receives Obj in method parameter