Last semester I taught an undergraduate course on system analysis and design using graphical modeling (UML and OPM). I decided that one important subject the students should learn (and was not taught in previous semesters) was design patterns. Although I already knew some of them, I searched for some place where there is a full reference of the most popular design patterns, what are their uses and how they should be implemented. I found some sources, one of them obviously Wikipedia, but the best one (in my view) is¬ sourcemaking, which gives good explanations and examples. Another great source was the c2 design patterns entry. Printing the nice one-page reference that can be found on Mark Gregory’s site¬†was also very helpful. But for me the most interesting (and strange thing) was that all the patterns are described using only class diagrams (which can only express structure) while the functionality provided by the patters was regularly explained either in words, with examples and with code. Why is it so? I asked myself. Why can’t we use sequence diagrams to describe these patterns? So after posting a question in stackoverflow on the subject, and receiving no answer, I decided to take on my challenge and provide the world with a repository of design patterns in sequence diagrams. And I’ll start with the singleton design pattern.
The singleton design pattern is a pattern used in OO when you want to allow the creation of one instance of a specific class. This is typical for utility classes and/or classes which manage resources. It’s class diagram looks like this:
To explain how a singleton should function, we can create a sequence diagram which shows how the two classes in our class diagram interact:
Notice that in the sequence diagram the two classes become three, because we need to interact with the getInstance method (which is class scoped) and with the creation of the new instance. This simple diagram is OK and tells us what should happen, but is not completely correct, specifically for multi-threaded environments, since two threads can enter the
opt fragment at the same time and both create a new instance.¬†Luckily sequence diagrams give us a notation to do this, using
critical¬†fragments, as shown below:
This sequence diagram shows us that there are two clients that can call the
getInstance method in parallel, but the creation of the
Singleton instance is protected in a critical region that must be enterd serially. While correct, this model is harder to understand than the original model and breaks the basic idea of sequence diagrams, which is to show sequential occurrence of events from top to bottom.
Another possible way show the implementation of a Singleton is to create a singleton that is initialized statically before the
getInstance method is called. This can be modeled as follows:
I did not find a good way to model the initialization of the
Singleton class therefore I stated this by using a UML annotation.
In conclusion, the Singleton design pattern can be modeled using sequence diagrams, although a correct model is fairly complex to understand (and harder to create!). The code that shows how to create a singleton that works in the multi-threaded environment is much shorter than the sequence diagram and much easier to understand, therefore the use of a sequence diagram in this case may be futile. But if you want to do it, it can be done.