Click here to Skip to main content
15,885,278 members
Articles / Programming Languages / C#
Tip/Trick

Monostate pattern

Rate me:
Please Sign up or sign in to vote.
4.94/5 (7 votes)
5 Dec 2013CPOL3 min read 33.9K   15   13
An interesting variation on the Singleton pattern

Introduction

An interesting variation on the Singleton pattern is the Monostate pattern, which also achieves singularity, but works through a completely different mechanism. Before we proceed any further, let me state that just like a Singleton, it too is in direct violation of the Single Responsibility Principle, in my opinion even more than the Singleton is. But it is so lovely wicked in behavior, that once in a while, you might find a good reason to use it.

Background

I have first encountered this pattern in a wonderful book, by Micah Martin and Robert C. Martin, "Agile Principles, Patterns and Practices in C#". While this pattern, or anti-pattern, has many uses, one must consider pros and cons of its implementation.

Pros: 

  • Transparency - users do not need to know that the object they use, is a Monostate.
  • Derivability -  derivatives of a Monostate continue to share static variables 
  • Polymorphism - only private static variables are shared, derivatives are free to override any methods of the base class 
  • Well-defined lifetime - being static, the variables of a Monostate have specific creation and destruction times 
Cons 

  • No conversion - you cannot derive a Monostate from a non-Monostate 
  • Efficiency - a Monostate might go through many creations and destructions, which might be quite expensive, depending on implementation 
  • Presence - even if the Monostate is never used, its variables take up space
  • Locality - they cannot be shared by multiple CLR instances
The Monostate pattern differs from Singleton, by enforcing singular behavior, without imposing constraints on structure.  

SINGLETON is best used when you have an existing class that you want to constrain through derivation and don’t mind that everyone will have to call the Instance() method to gain access. MONOSTATE is best used when you want the singular nature of the class to be transparent to the users or when you want to use polymorphic derivatives of the single object.

Martin, Micah; Martin, Robert C. (2006-07-20). Agile Principles, Patterns, and Practices in C# (Kindle Locations 6311-6313). Pearson Education. Kindle Edition.  

Using the code   

Let's take a look at this example:

C#
public class Monostate{
    private static int x;
    public int X
    {
        get { return x; }
        set { x = value; }
    }
}

Regardless of the number of times you will create or destroy an instance of this class, there will only be one value of X, shared across all threads of your application. In other words, changes made in one of your threads are immediately and instantaneously visible in all other threads. "Big Deal!" you say, but it gets much more interesting, once we incorporate Generics and Concurrent Collections:

C#
public class MonoConcurrentBag<T>
{
    #region Static Fields
    private static readonly ConcurrentBag<T> bag = new ConcurrentBag<T>();
    #endregion
    #region Public Properties
    public ConcurrentBag<T> Bag
    {
        get { return bag; }
    }
    #endregion
} 

Now we can proceed adding values from multiple threads and pretty much forget about any concurrency issues, or managing object lifetime.

C#
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
internal class Program
{
    #region Methods
    private static void Main(string[] args)
    {
        Parallel.Invoke(
            () => Parallel.For(
                0,
                1000,
                i =>
                {
                    var bag = new MonoConcurrentBag<int>();
                    bag.Bag.Add(i);
                }),
            () => Parallel.For(
                0,
                1000,
                i =>
                {
                    var bag = new MonoConcurrentBag<long>();
                    bag.Bag.Add(i);
                }));
        var anotherBag = new MonoConcurrentBag<int>();
        var anotherLongBag = new MonoConcurrentBag<long>();
        Console.WriteLine(anotherBag.Bag.Count);
        Console.WriteLine(anotherLongBag.Bag.Count);
    }
    #endregion
} 

If you run this sample code, it will print two lines, each with the number 1000.

I must admit, the first time I saw this pattern, I could not wrap my head around it. After all, in every iteration of the parallel loop, I ask the system to create a new instance of the class, and at the end of it, it should be destroyed and collected by the GC, so it was difficult to comprehend, how it can survive from one thread to another.

The key takeaway in this case is that static properties of a class, can and will live longer than an instance of the class itself. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect BI Software, Inc.
United States United States
A seasoned IT Professional. Programming and data processing artist. Contributor to StackOverflow.

Comments and Discussions

 
General[My vote of 1] TL;DR Static variables are static Pin
charoco5-Dec-13 5:58
charoco5-Dec-13 5:58 
GeneralRe: [My vote of 1] TL;DR Static variables are static Pin
Darek Danielewski5-Dec-13 6:02
Darek Danielewski5-Dec-13 6:02 
GeneralRe: [My vote of 1] TL;DR Static variables are static Pin
charoco5-Dec-13 9:22
charoco5-Dec-13 9:22 
My "I don't get it" referred to the purpose of the article, not the content of it. I would hope that the effect of having an instance property serve as a wrapper around a static variable would not be hard to grasp.

And no matter what Uncle Bob says, something so trivial hardly needs its own name. (And if anything, I'd call it an anti-pattern or code smell)
GeneralRe: [My vote of 1] TL;DR Static variables are static Pin
Darek Danielewski9-Dec-13 13:43
Darek Danielewski9-Dec-13 13:43 
QuestionAntipattern Singleton Pin
werinus5-Dec-13 4:43
werinus5-Dec-13 4:43 
AnswerRe: Antipattern Singleton Pin
Darek Danielewski5-Dec-13 5:13
Darek Danielewski5-Dec-13 5:13 
QuestionFlyweight Pin
Florian Rappl5-Dec-13 3:09
professionalFlorian Rappl5-Dec-13 3:09 
AnswerRe: Flyweight Pin
Darek Danielewski5-Dec-13 5:03
Darek Danielewski5-Dec-13 5:03 
QuestionHMMMM... Pin
FatCatProgrammer5-Dec-13 2:51
FatCatProgrammer5-Dec-13 2:51 
AnswerRe: HMMMM... Pin
Darek Danielewski5-Dec-13 5:06
Darek Danielewski5-Dec-13 5:06 
GeneralRe: HMMMM... Pin
FatCatProgrammer6-Dec-13 4:03
FatCatProgrammer6-Dec-13 4:03 
GeneralInteresting Pin
Omar Gameel Salem4-Dec-13 23:54
professionalOmar Gameel Salem4-Dec-13 23:54 
GeneralRe: Interesting Pin
Darek Danielewski5-Dec-13 5:13
Darek Danielewski5-Dec-13 5:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.