싱글톤 패턴
- 싱글톤 패턴은 해당 객체의 메모리를 정적으로 할당하여 하나의 객체에만 접근하는 방법입니다.
- 따라서 프로그램이 동작하는 동안 최초로 생성된 객체 하나에만 접근하게 되므로 데이터를 접근하고 수정이 용이합니다.
- 생성자를 다른 곳에서 새롭게 선언을 하더라도 이미 정적으로 선언된 객체가 반환되기 때문에 중복되어 생성되는 것을 방지 할 수 있습니다.
- 초기 객체를 생성을 하게 되면 정적 메모리에 올라가기 때문에 이후 호출하는데 아주 빠르게 접근할 수 있는 장점이 있습니다.
- 인스턴스를 생성할 때 매개변수를 지정하는 것을 문제가 추천하지 않습니다.
- 인스턴스를 여러번 호출할 수 있는데, 매개변수가 달라지는 경우 문제가 될 수 있습니다.
- 매개변수를 사용하여 인스턴스에 액세스 하는 경우엔
팩토리 패턴
이 더 적합합니다.
예제1
- 아래 예제에서 TableServer 클래스에서 servers라는 List를 생성합니다.
- TableServer()는 servers에 항목을 추가
- GetNextServer() : servers의 다음 항목을 반환
TableServer.cs
public class TableServer
{
private List<string> servers = new List<string>();
private int nextServer = 0;
public TableServer()
{
servers.Add("1");
servers.Add("2");
servers.Add("3");
servers.Add("4");
}
public string GetNextServer()
{
string output = servers[nextServer];
nextServer += 1;
if (nextServer >= servers.Count)
nextServer = 0;
return output;
}
}
Program.cs
public class Program
{
static void Main(string[] args)
{
var test = new TableServer();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("server is : " + test.GetNextServer());
}
Console.ReadLine();
}
}
출력 결과
예제2
- TableServer 인스턴스를 2개 생성합니다.
- Host1GetNext(), Host2GetNext() 메서드 생성합니다.
public class Program
{
static TableServer host1 = new TableServer();
static TableServer host2 = new TableServer();
static void Main(string[] args)
{
var test = new TableServer();
for (int i = 0; i < 5; i++)
{
//Console.WriteLine("server is : " + test.GetNextServer());
Host1GetNext();
Host2GetNext();
}
Console.ReadLine();
}
private static void Host1GetNext()
{
Console.WriteLine("host1 is : " + host1.GetNextServer());
}
private static void Host2GetNext()
{
Console.WriteLine("host2 is : " + host2.GetNextServer());
}
}
출력 결과
- host1, host2 각각의 리스트를 출력합니다.
- 이것은 Program 클래스 내부에 두개의 인스턴스가 존재하기 때문에 가능합니다.
- 하지만, 첫번째 결과와 동일하게 출력을 하고싶다면 어떻게 해야할까요.
- 우선 인스턴스끼리 동기화를 시켜줘야합니다.
예제3 (싱글톤 패턴 사용)
- 예제2의 문제를 해결하기 위해 싱글톤 패턴을 사용해봅시다.
- 우선 생성자를 private로 변경합니다.
private TableServer()
{
servers.Add("1");
servers.Add("2");
servers.Add("3");
servers.Add("4");
}
- _instance 멤버를 선언 및 초기화합니다.
- static을 사용함으로써 클래스를 인스턴스화하지 않고도 액세스 할 수 있습니다만,
- private을 사용하여 인스턴스화 하지지 않고 액세스 하는 이슈를 없앱니다.
- readonly를 사용함으로써 생성된 인스턴스의 값에 다른 인스턴스가 overwrite할 수 없게 됩니다.
private static readonly TableServer _instance = new TableServer();
- GetTableServer()생성합니다.
- public으로 지정함으로 써 TableServer의 인스턴스에서 GetTableServer()를 호출할 수 있습니다.
- 이 메서드에선 TableServer클래스의 인스턴스를 반환합니다.
- _instance를 반환함으로써,
new TableServer()
에 의하여 인스턴스가 생성됩니다. - 이 방법은 TableServer클래스를 인스턴스화 하는 유일한 방법입니다.
- GetTableServer()를 호출하기 전까지 인스턴스가 생성되지 않습니다.
public static TableServer GetTableServer()
{
return _instance;
}
- host1, host2 인스턴스 생성
- 인스턴스화 하는 방법이 달라졌으니, Program 클래스에서 host1,host2 인스턴스(객체) 생성 방법도 달라졌습니다.
static TableServer host1 = TableServer.GetTableServer();
static TableServer host2 = TableServer.GetTableServer();
Program.cs
public class Program
{
static TableServer host1 = TableServer.GetTableServer();
static TableServer host2 = TableServer.GetTableServer();
static void Main(string[] args)
{
//var test = new TableServer();
for (int i = 0; i < 10; i++)
{
//Console.WriteLine("server is : " + test.GetNextServer());
Host1GetNext();
Host2GetNext();
}
Console.ReadLine();
}
private static void Host1GetNext()
{
Console.WriteLine("host1 is : " + host1.GetNextServer());
}
private static void Host2GetNext()
{
Console.WriteLine("host2 is : " + host2.GetNextServer());
}
}
TableServer.cs
public class TableServer
{
private static readonly TableServer _instance = new TableServer();
private List<string> servers = new List<string>();
private int nextServer = 0;
private TableServer()
{
servers.Add("1");
servers.Add("2");
servers.Add("3");
servers.Add("4");
}
//public으로 지정함으로 써 TableServer의 인스턴스에서 GetTableServer()를 호출할 수 있습니다.
public static TableServer GetTableServer()
{
return _instance;
}
public string GetNextServer()
{
string output = servers[nextServer];
nextServer += 1;
if (nextServer >= servers.Count)
nextServer = 0;
return output;
}
}
출력 결과
- 예제2의 문제가 해결됐습니다.
- host1과 host2에서 GetNextServer()를 호출하여 인스턴스를 요청했고, 동일한 인스턴스를 얻었습니다.
- 그리고 Host1GetNext(), Host2GetNext()에서 동일한 인스턴스의 GetNextServer()를 호출했기 예제2의 문제점이 해결된 것입니다.
- 싱글톤 패턴은 다른 App사이에서 데이터를 공유할 때 유용할 것입니다.
'프로그래밍 > C#' 카테고리의 다른 글
[WPF] INotifyPropertyChanged 구현 (0) | 2022.10.07 |
---|---|
[WPF] Textbox 값 변경 이벤트 (0) | 2022.10.07 |
[C#] ? 와 ?? 연산자 (0) | 2022.06.22 |
[C#] 의존성 주입 (Dependency Injection) (0) | 2022.06.06 |
[C#] 람다연산자 => (0) | 2022.06.06 |