Skip to content

Commit 5b52425

Browse files
committed
Add Singleton implementation.
1 parent 7465f32 commit 5b52425

7 files changed

+304
-16
lines changed

Singleton/Participants.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+


Singleton/Program.OptimizedCode.cs

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
/// <summary>
5+
/// The.NET optimized code demonstrates the same code as above but uses more modern, built-in .NET features.
6+
/// Here an elegant .NET specific solution is offered.The Singleton pattern simply uses a private constructor
7+
/// and a static readonly instance variable that is lazily initialized.Thread safety is guaranteed by the compiler.
8+
/// </summary>
9+
namespace DoFactory.GangOfFour.Singleton.NETOptimized
10+
{
11+
/// <summary>
12+
/// MainApp startup class for .NET optimized
13+
/// Singleton Design Pattern.
14+
/// </summary>
15+
class MainApp
16+
{
17+
/// <summary>
18+
/// Entry point into console application.
19+
/// </summary>
20+
static void Main()
21+
{
22+
LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
23+
LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
24+
LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
25+
LoadBalancer b4 = LoadBalancer.GetLoadBalancer();
26+
27+
// Confirm these are the same instance
28+
if (b1 == b2 && b2 == b3 && b3 == b4)
29+
{
30+
Console.WriteLine("Same instance\n");
31+
}
32+
33+
// Next, load balance 15 requests for a server
34+
LoadBalancer balancer = LoadBalancer.GetLoadBalancer();
35+
for (int i = 0; i < 15; i++)
36+
{
37+
string serverName = balancer.NextServer.Name;
38+
Console.WriteLine("Dispatch request to: " + serverName);
39+
}
40+
41+
// Wait for user
42+
Console.ReadKey();
43+
}
44+
}
45+
46+
/// <summary>
47+
/// The 'Singleton' class
48+
/// </summary>
49+
sealed class LoadBalancer
50+
{
51+
// Static members are 'eagerly initialized', that is,
52+
// immediately when class is loaded for the first time.
53+
// .NET guarantees thread safety for static initialization
54+
private static readonly LoadBalancer _instance =
55+
new LoadBalancer();
56+
57+
// Type-safe generic list of servers
58+
private List<Server> _servers;
59+
private Random _random = new Random();
60+
61+
// Note: constructor is 'private'
62+
private LoadBalancer()
63+
{
64+
// Load list of available servers
65+
_servers = new List<Server>
66+
{
67+
new Server{ Name = "ServerI", IP = "120.14.220.18" },
68+
new Server{ Name = "ServerII", IP = "120.14.220.19" },
69+
new Server{ Name = "ServerIII", IP = "120.14.220.20" },
70+
new Server{ Name = "ServerIV", IP = "120.14.220.21" },
71+
new Server{ Name = "ServerV", IP = "120.14.220.22" },
72+
};
73+
}
74+
75+
public static LoadBalancer GetLoadBalancer()
76+
{
77+
return _instance;
78+
}
79+
80+
// Simple, but effective load balancer
81+
public Server NextServer
82+
{
83+
get
84+
{
85+
int r = _random.Next(_servers.Count);
86+
return _servers[r];
87+
}
88+
}
89+
}
90+
91+
/// <summary>
92+
/// Represents a server machine
93+
/// </summary>
94+
class Server
95+
{
96+
// Gets or sets server name
97+
public string Name { get; set; }
98+
99+
// Gets or sets server IP address
100+
public string IP { get; set; }
101+
}
102+
}
103+
104+
//Output
105+
106+
//Same instance
107+
108+
//ServerIV
109+
//ServerIV
110+
//ServerIII
111+
//ServerV
112+
//ServerII
113+
//ServerV
114+
//ServerII
115+
//ServerII
116+
//ServerI
117+
//ServerIV
118+
//ServerIV
119+
//ServerII
120+
//ServerI
121+
//ServerV
122+
//ServerIV

Singleton/Program.RealWorldCode.cs

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading;
4+
5+
namespace DoFactory.GangOfFour.Singleton.RealWorld
6+
{
7+
/// <summary>
8+
/// MainApp startup class for Real-World
9+
/// Singleton Design Pattern.
10+
/// </summary>
11+
class MainApp
12+
{
13+
/// <summary>
14+
/// Entry point into console application.
15+
/// </summary>
16+
static void Main()
17+
{
18+
LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
19+
LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
20+
LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
21+
LoadBalancer b4 = LoadBalancer.GetLoadBalancer();
22+
23+
// Same instance?
24+
if (b1 == b2 && b2 == b3 && b3 == b4)
25+
{
26+
Console.WriteLine("Same instance\n");
27+
}
28+
29+
// Load balance 15 server requests
30+
LoadBalancer balancer = LoadBalancer.GetLoadBalancer();
31+
for (int i = 0; i < 15; i++)
32+
{
33+
string server = balancer.Server;
34+
Console.WriteLine("Dispatch Request to: " + server);
35+
}
36+
37+
// Wait for user
38+
Console.ReadKey();
39+
}
40+
}
41+
42+
/// <summary>
43+
/// The 'Singleton' class
44+
/// </summary>
45+
class LoadBalancer
46+
{
47+
private static LoadBalancer _instance;
48+
private List<string> _servers = new List<string>();
49+
private Random _random = new Random();
50+
51+
// Lock synchronization object
52+
private static object syncLock = new object();
53+
54+
// Constructor (protected)
55+
protected LoadBalancer()
56+
{
57+
// List of available servers
58+
_servers.Add("ServerI");
59+
_servers.Add("ServerII");
60+
_servers.Add("ServerIII");
61+
_servers.Add("ServerIV");
62+
_servers.Add("ServerV");
63+
}
64+
65+
public static LoadBalancer GetLoadBalancer()
66+
{
67+
// Support multithreaded applications through
68+
// 'Double checked locking' pattern which (once
69+
// the instance exists) avoids locking each
70+
// time the method is invoked
71+
if (_instance == null)
72+
{
73+
lock (syncLock)
74+
{
75+
if (_instance == null)
76+
{
77+
_instance = new LoadBalancer();
78+
}
79+
}
80+
}
81+
82+
return _instance;
83+
}
84+
85+
// Simple, but effective random load balancer
86+
public string Server
87+
{
88+
get
89+
{
90+
int r = _random.Next(_servers.Count);
91+
return _servers[r].ToString();
92+
}
93+
}
94+
}
95+
}
96+
97+
98+
//Output
99+
100+
//Same instance
101+
102+
//ServerIII
103+
//ServerII
104+
//ServerI
105+
//ServerII
106+
//ServerI
107+
//ServerIII
108+
//ServerI
109+
//ServerIII
110+
//ServerIV
111+
//ServerII
112+
//ServerII
113+
//ServerIII
114+
//ServerIV
115+
//ServerII
116+
//ServerIV

Singleton/Program.Structural.cs

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
3+
namespace DoFactory.GangOfFour.Singleton.Structural
4+
{
5+
/// <summary>
6+
/// MainApp startup class for Structural
7+
/// Singleton Design Pattern.
8+
/// </summary>
9+
class MainApp
10+
{
11+
/// <summary>
12+
/// Entry point into console application.
13+
/// </summary>
14+
static void Main()
15+
{
16+
// Constructor is protected -- cannot use new
17+
Singleton s1 = Singleton.Instance();
18+
Singleton s2 = Singleton.Instance();
19+
20+
// Test for same instance
21+
if (s1 == s2)
22+
{
23+
Console.WriteLine("Objects are the same instance");
24+
}
25+
26+
// Wait for user
27+
Console.ReadKey();
28+
}
29+
}
30+
31+
/// <summary>
32+
/// The 'Singleton' class
33+
/// </summary>
34+
class Singleton
35+
{
36+
private static Singleton _instance;
37+
38+
// Constructor is 'protected'
39+
protected Singleton()
40+
{
41+
}
42+
43+
public static Singleton Instance()
44+
{
45+
// Uses lazy initialization.
46+
// Note: this is not thread safe.
47+
if (_instance == null)
48+
{
49+
_instance = new Singleton();
50+
}
51+
52+
return _instance;
53+
}
54+
}
55+
}
56+
//Output
57+
58+
//Objects are the same instance

Singleton/Program.cs

-15
This file was deleted.

Singleton/Singleton.csproj

+7-1
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,18 @@
4242
<Reference Include="System.Xml" />
4343
</ItemGroup>
4444
<ItemGroup>
45-
<Compile Include="Program.cs" />
45+
<Compile Include="Program.OptimizedCode.cs" />
46+
<Compile Include="Program.RealWorldCode.cs" />
47+
<Compile Include="Program.Structural.cs" />
4648
<Compile Include="Properties\AssemblyInfo.cs" />
4749
</ItemGroup>
4850
<ItemGroup>
4951
<None Include="App.config" />
5052
</ItemGroup>
53+
<ItemGroup>
54+
<Content Include="Participants.txt" />
55+
<Content Include="singleton.gif" />
56+
</ItemGroup>
5157
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
5258
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
5359
Other similar extension points exist, see Microsoft.Common.targets.

Singleton/singleton.gif

2.46 KB
Loading

0 commit comments

Comments
 (0)