I have been doing a rushed brush up on my contemporary concepts programming course – only to encounter more design patterns… so as revision I have listed some details below…
Today I am going to briefly cover 5 design patterns… namely:
- Composite Pattern
- Observer Pattern
- Serializer Pattern
- Monostate Pattern
- Command Pattern
What are Design Patterns? (see wiki)
In programming we come across problems that are very similar, and certain approaches to solving these problems could be applied time and time again. Design patterns are an attempt to express the “best” approach so that it is reusable.
Composite Pattern
The composite pattern is typically used when you want to treat a tree of objects as one object.
To build a tree of objects, you first need a composite class at the root of the tree and then add children to the composite class. A common scenario of implementing the composite pattern is for cad systems when a drawing can consist of a collection of sub items – each item needs to be drawn, but you would only want to trigger the draw state on the entire drawing…
This may all be a bit abstract to explain, but easier to look at the code to see what is happening…
With the c# implementation you will have a files…
- Abstract class that would outline the common functions across each composite or leaf
- An implementation of the composite class based on the abstract class
- An implementation of the leaf class based on the abstract class
Abstract Class
// the single interface for primitives & composite types.|publicabstractclass CompositeComponent {abstractpublicvoid AddChild(CompositeComponent c);abstractpublicvoid Draw(); }
Composite Class
publicclass Composite : CompositeComponent {privatestring _value = "";private List<CompositeComponent> _componentList = new List<CompositeComponent>();public Composite(stringvalue) { _value = value; }publicoverridevoid AddChild(CompositeComponent c) { _componentList.Add(c); }publicoverridevoid Draw() { Console.WriteLine("Draw Composite : {0} ", _value);foreach (var itm in _componentList) { itm.Draw(); } } }
Leaf Class
publicclass Leaf : CompositeComponent {privatestring _value = "";public Leaf(stringvalue) { _value = value; }publicoverridevoid AddChild(CompositeComponent c) {thrownew Exception("Cannot add to a leaf"); }publicoverridevoid Draw() { Console.WriteLine("Draw Leaf : {0}", _value); } }
Example of an implementation
class Program {staticvoid Main(string[] args) {// Creating a TREE structure. Composite root = new Composite("Root"); Composite com1 = new Composite("Composite 1"); Leaf leaf1 = new Leaf("Leaf 1"); Leaf leaf2 = new Leaf("Leaf 2"); Leaf leaf3 = new Leaf("Leaf 3");// Add two leafs to composite1 com1.AddChild(leaf1); com1.AddChild(leaf2); Console.WriteLine("Example 1 - Draw Composite"); com1.Draw(); root.AddChild(leaf3); root.AddChild(com1); // Single method for both types. Console.WriteLine("\n \nExample 2 - Draw Root"); root.Draw(); Console.ReadLine(); } }
Output of Example
Image may be NSFW.
Clik here to view.
QT’s specific implementation of the composite pattern
In QT, the QObject class represents the application of a simplified form of the composite pattern, however unlike my representation in the code below, in QT they have implemented the component and the composite into the same class.
To make one object the child of another with the QTObject you simply call the setParent. This is where it varies form the classic composite pattern as it does not have a set child method.
Monostate Pattern
Sometimes you may have situations where you want to be able to access across the application, for instance a General Settings object. In the past I have used the singleton pattern to apply this. The one downside of a singleton class is that if at a later stage you want to change the object so that it is a normal object, you need to go to every point where you referenced the singleton and change it to a normal object.
(Drum Roll) enter the Monostate Pattern (End Drum Roll)
The Monostate pattern tries to accomplish something similar to a singleton pattern, but in a very different way. It makes a object look to the outside user as if it is a normal class, however whenever you access data members of the class you are in fact accessing the same data. The simplest way to achieve the monostate pattern is to make all the data members of the class static. Whether this is a good thing or a bad thing is probably up to the beholder, but it is interesting to have a quick look at how this is implemented…
publicclass Monostate { privatestaticstring _dataItem; //static datapublicstring DataItem { get { return _dataItem; } set { _dataItem = value; } } }
Looking at using this class we can see how the fact that it is accessing a static instance of the object is hidden…
staticvoid Main(string[] args) { Monostate myobj1 = new Monostate(); myobj1.DataItem = "123"; Monostate myobj2 = new Monostate(); myobj2.DataItem = "456"; Console.WriteLine("Object 1 : {0}", myobj1.DataItem); Console.WriteLine("Object 2 : {0}", myobj2.DataItem); Console.ReadLine(); }
This would give you the following output…
Image may be NSFW.
Clik here to view.
Which from what you can see myobj1 DataItem has changed even though it was not apparent when looking at the code of the main class.
Observer Pattern
The observer pattern is useful when you want a number of objects to view/react to the state of a particular object without the object having to specifically tell them to react. In the classic observer pattern you will have two abstract classes – one for the subject and one for the observer. You then can have objects that implement the abstract observer or abstract subject…
Lets have a look at an example abstract subject and observer class…
abstractclass Subject {private List<Observer> _observers = new List<Observer>();publicvoid Attach(Observer observer) { _observers.Add(observer); }publicvoid Detach(Observer observer) { _observers.Remove(observer); }publicvoid Notify() {foreach (Observer o in _observers) { o.Update(); } } }
abstractclass Observer {publicabstractvoid Update(); }
You can now have concrete implementation of each class as illustrated below…
/// <summary>/// The 'ConcreteSubject' class/// </summary>class ConcreteSubject : Subject {privatestring _subjectState;// Gets or sets subject statepublicstring SubjectState { get { return _subjectState; } set { _subjectState = value; } } }/// <summary>/// The 'ConcreteObserver' class/// </summary>class ConcreteObserver : Observer {privatestring _name;privatestring _observerState; // Constructorpublic ConcreteObserver(ConcreteSubject subject, string name) {this.Subject = subject;this._name = name; }publicoverridevoid Update() { _observerState = Subject.SubjectState; Console.WriteLine("Observer {0}'s new state is {1}", _name, _observerState); }// Gets or sets subjectpublic ConcreteSubject Subject { get; set; } }
An implementation of the these classes is illustrated below…
staticvoid Main(string[] args) { // Configure Observer pattern ConcreteSubject s = new ConcreteSubject(); ConcreteObserver ObserverObject1 = new ConcreteObserver(s, "Object1"); ConcreteObserver ObserverObject2 = new ConcreteObserver(s, "Object2"); ConcreteObserver ObserverObject3 = new ConcreteObserver(s, "Object3"); s.Attach(ObserverObject1); s.Attach(ObserverObject2); s.Attach(ObserverObject3); // Change subject and notify observers s.SubjectState = "ABC"; s.Notify();//Detach one observer s.Detach(ObserverObject2); // Change subject and notify observers s.SubjectState = "CDE"; s.Notify();// Wait for user Console.ReadKey(); ; }
Which would give the following output…
Image may be NSFW.
Clik here to view.
Just to keep in mind that the observer pattern is very similar to the event aggregator pattern used commonly in MVVM application.
QT’s specific implementation of the observer pattern
The QObject class represents the application of a simplified observer pattern in its use of signals and slots. QObject represents the Subject, Observer, ConcreteSubject and ConcreteObserver classes all rolled into one.
QObject has a static member called connect() which is used to connect a subject to an observer. It also allows you to specify which change of state (the signal) should cause which update (the slot). Numerous observers can be connected to a single subject, and one observer can be connected to numerous subjects.
Serializer Pattern
Due to time constraints I am not going to go into to much detail on this pattern, other than a brief explanation…
The serializer pattern is such that if you want to save/load the state of an object to the screen or file, instead of implementing the read and write methods inside the class, instead you implement a separate reader and writer class that accepts the targeted class as a parameter.
Command Pattern
Again a fairly common pattern, but one I am not going to go into to much detail in this post.
QT’s specific implementation of the command pattern
The closest we get in QT to the classic command pattern is with the QAction object. All events are represented by objects of type QAction. The rest of the classes in the classic Command pattern do not have direct equivalents in QT.