Change log

Home

Singleton pattern

Links

Waarom deze versie niet

Hier wordt een object teruggeven vanuit zijn class-definitie, dit houdt o.a. in dat er meer beschikbaar is dan wenselijk kan zijn. Als je de interface teruggeeft is dit beter te beheersen. Zo weet je bijvoorbeeld zeker dat er geen constructor beschikbaar is voor derden, op deze manier wordt oneigenlijk gebruik behoorlijk effectief tegengehouden.
Bij het instantieĆ«ren van een Singleton wil je er in de Factory ook zeker van zijn dat dit echt een Singleton is. Dit is voor een subclass vrij eenvoudig vast te stellen, voor een interface is dat wat lastiger.
Verder zijn de afgeleide interfaces en classes een stuk doorzichtiger als een interface wordt gebruikt als basis, met als extra voordeel dat reeds bestaande class-definities op een eenvoudige manier een Singleton interface kunnen gaan implementeren, als dat nodig is.


Een thread-safe singleton baseclass in C# met SingletonFactory. (versie 1)
using System;
using System.Reflection;
using System.Collections;
using System.Threading;

namespace DesignPatterns
{
public class SingletonException : Exception 
{
public SingletonException(string message): base(message){}
}
          
public class SingletonFactory
{
static private Hashtable singletonTable = new Hashtable();

public class Singleton
    {
    }
    
static protected Singleton Instance(Type SingletonType)
    {
    Object _singleton = null;
    string WarningMessage = ": class must have Singleton as a baseclass";
      
    if (!SingletonType.IsSubclassOf(typeof(Singleton)))
    throw new SingletonException(SingletonType.ToString() + WarningMessage);
      
    Mutex mutex = new Mutex();
    mutex.WaitOne();

    _singleton = singletonTable[SingletonType];
    if (_singleton == null)
    {
    _singleton = Activator.CreateInstance(SingletonType);
    singletonTable.Add(SingletonType, _singleton);
    }
        
    mutex.Close();
      
    return _singleton as Singleton;
    }
}
}
Een SingletonFactory implementatie.
using System;

namespace DesignPatterns
{
public interface derivedSingleton
{
string name { get; set; }
}
  
public interface SingletonA : derivedSingleton
{
}

public interface SingletonB : derivedSingleton 
{
}
  
internal class derivedSingletonClass : SingletonFactory.Singleton, derivedSingleton
{
private string _name;
public  string  name { get {return _name;} set {_name = value;}}
}
    
internal class SingletonAClass : derivedSingletonClass, SingletonA
{
}
    
internal class SingletonBClass : derivedSingletonClass, SingletonB
{
}
  
public class MySingletonFactory : SingletonFactory
{
public MySingletonFactory()
    {
    }
    
static public SingletonA singletonA()
    {
    return Instance(typeof(SingletonAClass)) as SingletonA;
    }
      
static public SingletonB singletonB()
    {
    return Instance(typeof(SingletonBClass)) as SingletonB;
    }
}
}
En een Form om de code in werking te zien.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using DesignPatterns;

namespace SingletonTest
{
public class SingletonForm : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
		
public SingletonForm()
    {
    InitializeComponent();
    }
		
protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if (components != null) 
        {
        components.Dispose();
        }
    }
    base.Dispose( disposing );
    }

#region Windows Form Designer generated code
private void InitializeComponent()
    {
    this.button1 = new System.Windows.Forms.Button();
    this.SuspendLayout();
    // 
    // button1
    // 
    this.button1.Location = new System.Drawing.Point(42, 32);
    this.button1.Name = "button1";
    this.button1.Size = new System.Drawing.Size(104, 23);
    this.button1.TabIndex = 0;
    this.button1.Text = "Show singletons";
    this.button1.Click += new System.EventHandler(this.button1_Click);
    // 
    // SingletonForm
    // 
    this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
    this.ClientSize = new System.Drawing.Size(192, 101);
    this.Controls.Add(this.button1);
    this.Name = "SingletonForm";
    this.Text = "Singleton test";
    this.ResumeLayout(false);

    }
#endregion

[STAThread]
static void Main() 
    {
    Application.Run(new SingletonForm());
    }

private void button1_Click(object sender, System.EventArgs e)
    {
    string ShowString = "";
      
    SingletonA TestSingletonA  = MySingletonFactory.singletonA();
    SingletonB TestSingletonB1 = MySingletonFactory.singletonB();
    SingletonB TestSingletonB2 = MySingletonFactory.singletonB();
      
    TestSingletonB2.name = "B2";
    TestSingletonB1.name = "B1";
    TestSingletonA.name  = "A";
      
    ShowString = "value of name in A/B1/B2 : " 
            + TestSingletonA.name + "/" 
            + TestSingletonB1.name + "/" 
            + TestSingletonB2.name;
      
    MessageBox.Show(this, ShowString, "Sample", MessageBoxButtons.OK);
    }
}
}
Top
10 oktober 2004 Waarom niet
2 oktober 2004 CSharp Singleton code page naar nieuwe url overgezet, design aangepast.

24-10-2017/22-11-2024

konfidence in it (c) 2004