Definition

Ensure a class has only one instance and provide a global point of access to it.

 

Participants


The classes and/or objects participating in this pattern are:

 Singleton (LoadBalancer)

  •  defines an Instance operation that lets clients access its unique instance.Instance is a class operation. 
  •  responsible for creating and maintaining its own unique instance.

 

Singleton: when and where use it

Most objects in an application are responsible for their own work and operate on self-contained data and references that are within their given area of concern. However, there are objects that have additional responsibilities and are more global in scope, such as, managing limited resources or monitoring the overall state of the system.

The responsibilities of these objects often require that there be just one instance of the class. Examples include cached database records (see TopLink by Oracle), or a
scheduling service which regularly emails work-flow items that require attention. Having more than one database or scheduling service would risk duplication and may result in all kinds of problems. 


Other areas in the application rely on these special objects and they need a way to find them. This is where the Singleton design pattern comes in. The intent of the Singleton pattern is to ensure that a class has only one instance and to provide a global point of access to this instance. Using the Singleton pattern you centralize authority over a particular resource in a single object.

Other reasons quoted for using Singletons are to improve performance. A common scenario is when you have a stateless object that is created over and over again. A Singleton removes the need to constantly create and destroy objects. Be careful though as the Singleton may not be the best solution in this scenario; an alternative would be to make your methods static and this would have the same effect. Singletons have the unfortunate reputation for being overused by „pattern happy‟ developers.

Global variables are frowned upon as a bad coding practice, but most practitioners acknowledge the need for a few globals. Using Singleton you can hold one or more
global variables and this can be really handy. In fact, this is how Singletons are frequently used – they are an ideal place to keep and maintain globally accessible
variables.

 

using System;
using System.Collections.Generic;
using System.Threading;

namespace DoFactory.GangOfFour.Singleton.RealWorld
{
    /// <summary>
    /// MainApp startup class for Real-World 
    /// Singleton Design Pattern.
    /// </summary>
    class MainApp
    {
        /// <summary>
        /// Entry point into console application.
        /// </summary>
        static void Main()
        {
            LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

            // Same instance?
            if (b1 == b2 && b2 == b3 && b3 == b4)
            {
                Console.WriteLine("Same instance\n");
            }

            // Load balance 15 server requests
            LoadBalancer balancer = LoadBalancer.GetLoadBalancer();
            for (int i = 0; i < 15; i++)
            {
                string server = balancer.Server;
                Console.WriteLine("Dispatch Request to: " + server);
            }

            // Wait for user
            Console.ReadKey();
        }
    }

    /// <summary>
    /// The 'Singleton' class
    /// </summary>
    class LoadBalancer
    {
        private static LoadBalancer _instance;
        private List<string> _servers = new List<string>();
        private Random _random = new Random();

        // Lock synchronization object
        private static object syncLock = new object();

        // Constructor (protected)
        protected LoadBalancer()
        {
            // List of available servers
            _servers.Add("ServerI");
            _servers.Add("ServerII");
            _servers.Add("ServerIII");
            _servers.Add("ServerIV");
            _servers.Add("ServerV");
        }

        public static LoadBalancer GetLoadBalancer()
        {
            // Support multithreaded applications through
            // 'Double checked locking' pattern which (once
            // the instance exists) avoids locking each
            // time the method is invoked
            if (_instance == null)
            {
                lock (syncLock)
                {
                    if (_instance == null)
                    {
                        _instance = new LoadBalancer();
                    }
                }
            }

            return _instance;
        }

        // Simple, but effective random load balancer
        public string Server
        {
            get
            {
                int r = _random.Next(_servers.Count);
                return _servers[r].ToString();
            }
        }
    }
}

 

posted on 2014-09-01 11:47  pulove  阅读(336)  评论(0编辑  收藏  举报