Click here to Skip to main content
Click here to Skip to main content

Implementing design patterns in C#

, 31 Jan 2003
Rate this:
Please Sign up or sign in to vote.
Implementing Singleton and AbstractFactory patterns in C#

Introduction

Singleton ------- Creational Design pattern

Use the Singleton Pattern when:

  1. There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.
  2. When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code.

Example

The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance. It is named after the singleton set, which is defined to be a set containing one element. The office of the President of the United States is a Singleton. There can be at most one active president at any given time. Regardless of the personal identity of the active president, the title, "The President of the United States" is a global point of access that identifies the person in the office.

Singleton Code

Make the class of the single instance object responsible for creation, initialization, and access. Declare the instance as a private static data member. Provide a public static member function that encapsulates all initialization code, and provide access to the instance.

class Singleton {
        private static Singleton uniqueInstance; // own instance
    
        private Singleton() {
        }
    
        public static Singleton GetInstance() {
    
            // 'lazy' evaluate instance
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
    
            return uniqueInstance;
        }
    
        public void WriteSomething() {
            Console.WriteLine("Singleton.WriteSomething() running" );
        }
    }// end of the class singleton

Revision 1.1

Since the above code is not thread safe, and from the users' comments, I have decided to make it thread safe. Hope this helps. Here is the code for the thread-safe Singleton, the one which works in a multi-threaded environment.

namespace ThreadSafeSingleTon
{
    /// <span class="code-SummaryComment"><summary>
</span>
    /// TSSingleton class implements the thread-safe version of the Singleton 
    /// design pattern. This class is designed
    /// to be used to provide the singleton 
    /// across threads in a multi-threaded application.
    /// <span class="code-SummaryComment"></summary>
</span>
    public sealed class TSSingleton
    {
        private static volatile TSSingleton    instance = null;
        private static object syncObj = new object();

        // make the default constructor private,
        // so that no can directly create it.
        private TSSingleton()
        {
        }

        // public property that can only get
        // the single instance of this class.
        public static TSSingleton Instance
        {
            get 
            {
                // only create a new instance if one doesn't already exist.
                if (instance == null)
                {
                    // use this lock to ensure that only one thread is access
                    // this block of code at once.
                    lock(syncObj)
                    {
                        if (instance == null)
                            instance = new TSSingleton();
                    }
                }
                // return instance where it was just
                // created or already existed.
                return instance;
            }
        }
    }
}

// code to access the Singleton.
using System.Diagnostics;

As you can see, this class is similar in structure to the Singleton class. The instance member variable is no longer set at creation time, but in the Instance property instead. The instance variable is declared to be volatile in order to assure that the assignment of instance is complete before the instance can be accessed.

The syncObj object is used to lock on. The lock ensures that only one thread can access the instance creation code at once. That way, you won't get into a situation where two different threads are trying to create the singleton simultaneously.

Abstract Factory ---- Creational Pattern

Trying to maintain portability across multiple platforms requires lots of preprocessor "case" statements. The Factory pattern suggests defining a creation services interface in a factory base class, and implementing each platform in a separate Factory derived class. If an application is to be portable, it needs to encapsulate platform dependencies. These "platforms" might include: windowing system, operating system, database, etc. Too often, this encapsulation is not engineered in advance, and lots of #ifdef case statements with options for all currently supported platforms begin to procreate like mushrooms throughout the code.

Abstract Factory simplifies the creation of different classes of same family by providing with a Contract. It is like saying ‘to enter United states, you need to agree with the contract’.

Abstract Factory Code

using System;
using System.Diagnostics;
namespace abstractfact{

    abstract class MainWindow { 
        abstract public void draw();
    };
    class UnixSystem : MainWindow {
        override public void draw() { Console.WriteLine("UnixSystem");}
    };
    class WindowsSystem : MainWindow {
        override public void draw() { Console.WriteLine("WindowsSystem"); }
    };
    abstract class Factory { 
        abstract public MainWindow whichSystem();
    };
    class UnixFactory :  Factory {
        override public MainWindow whichSystem() {return new UnixSystem(); }
    };
    class WindowsFactory :Factory {
        override public    MainWindow whichSystem() { return new WindowsSystem(); }
    };
    class SimilarWindows {
        private MainWindow mainWind;
        public SimilarWindows( Factory factory ){
        // create window, 
            mainWind = factory.whichSystem();
        }
        public void Run()
        {
            mainWind.draw(); 
          }    
    }

    class AbstractImpl
    {
        [STAThread]
        static void Main(string[] args)
        {
            #if UNIX
                Factory factory = new UnixFactory();
            #else 
                Factory factory = new WindowsFactory();
            #endif
                MainWindow w =     factory.whichSystem();
                w.draw();
            SimilarWindows s = new SimilarWindows(factory);
            s.Run()        ;
        }
    }

}
// output 
//WindowsSystem
//WondowsSystem

The Factory pattern suggests defining a creation services interface in a Factory base class, and implementing each "platform" in a separate Factory derived class.

More design patterns will be posted soon...

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author


Comments and Discussions

 
GeneralA better singleton implementation, you decide PinmemberKing Rufus5-Feb-03 6:53 
GeneralRe: A better singleton implementation, you decide Pinmemberjulio3615-Jul-04 15:39 
GeneralRe: A better singleton implementation, you decide Pinmemberadonisv9-Jul-04 11:20 
GeneralSingleton broken in multi-threaded environment PinsussChaotic_Evil3-Feb-03 5:09 
GeneralRe: Singleton broken in multi-threaded environment PinmemberArun Bhalla4-Feb-03 14:48 
GeneralRe: Singleton broken in multi-threaded environment PinmemberChris Meech5-Feb-03 8:18 
GeneralRe: Singleton broken in multi-threaded environment PinmemberChaotic_Evil5-Feb-03 8:44 
GeneralRe: Singleton broken in multi-threaded environment PinmemberChris Meech5-Feb-03 8:51 
GeneralRe: Singleton broken in multi-threaded environment PinmemberChaotic_Evil5-Feb-03 9:52 
GeneralRe: Singleton broken in multi-threaded environment PinmemberChris Meech5-Feb-03 10:20 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.141022.2 | Last Updated 1 Feb 2003
Article Copyright 2003 by Samar Aarkotti
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid