이 기사에서는 생성 모드에서 세 번째로 가장 일반적으로 사용되는 모드인 싱글톤 모드를 살펴봅니다. 그래도 두 장의 사진을 먼저 보고, 모드 종류를 복습하고, 기억을 더 깊게 하는 것이다.
정의:
싱글톤 모드: 클래스에 인스턴스가 하나만 있는지 확인하고 이 고유한 인스턴스에 액세스할 수 있는 전역 액세스 지점을 제공합니다 .
싱글톤 패턴: 클래스에 인스턴스가 하나만 있는지 확인 하고 글로벌 액세스 지점을 제공합니다.
주요 요점:
클래스는 하나의 인스턴스만 가질 수 있습니다.
이 인스턴스를 직접 만들어야 합니다.
이 인스턴스를 전체 시스템 자체에 제공 해야 합니다.
가장 간단한 실제 사례는 Windows 운영 체제의 작업 관리자와 로드 밸런싱의 고유성입니다.
구조:
분류:
배고픈 스타일의 싱글톤 클래스: 여러 스레드가 동시에 액세스하는 문제를 고려할 필요가 없습니다. 호출 속도와 응답 시간이 게으른 스타일의 싱글톤보다 낫습니다. 리소스 활용 효율성이 게으른 스타일의 싱글톤보다 좋지 않습니다. 시스템 로딩 시간이 더 길게
class EagerSingleton
{
private static EagerSingleton instance = new EagerSingleton();
private EagerSingleton() { }
public static EagerSingleton GetInstance()
{
return instance;
}
}
지연 스타일 싱글톤 클래스: 지연 로드 구현, 동시에 여러 스레드 액세스 문제를 처리해야 함, 이중 확인 잠금과 같은 메커니즘으로 제어해야 시스템 성능이 어느 정도 영향을 받음
class Singleton
{
private static Singleton instance=null;
private Singleton()
{
}
public static Singleton GetInstance()
{
if(instance==null)
instance=new Singleton();
return instance;
}
}
다른 프로세스에 의한 반복 호출을 방지하는 게으른 스타일, 잠금을 두 번 확인할 수 있습니다.
class LazySingleton
{
private static LazySingleton instance = null;
//程序运行时创建一个静态只读的辅助对象
private static readonly object syncRoot = new object();
private LazySingleton() { }
public static LazySingleton GetInstance()
{
//第一重判断,先判断实例是否存在,不存在再加锁处理
if (instance == null)
{
//加锁的程序在某一时刻只允许一个线程访问
lock(syncRoot)
{
//第二重判断
if(instance==null)
{
instance = new LazySingleton(); //创建单例实例
}
}
}
return instance;
}
}
클래스 다이어그램:
적용 가능성:
시스템에
하나의 인스턴스 객체만 필요하거나
너무 많은 리소스 소비로 인해
하나의 객체만 생성할 수 있습니다.
클라이언트 호출 클래스의 단일 인스턴스는
하나의 공용 액세스 포인트만 사용할 수
있으며 공용 액세스 포인트 이외의 다른 수단을 통해 인스턴스에 액세스할 수 없습니다.
이점:
고유한 인스턴스에 대한 제어된 액세스 제공
시스템 리소스를 절약
하고
시스템 성능을 향상시킬 수 있습니다.
가변 개수의 인스턴스 허용(
여러 인스턴스 클래스
)
결점:
확장 어려움
(추상화 계층 부족)
Singleton 클래스에는
너무 많은 책임이 있습니다.
자동 가비지 수집 메커니즘으로 인해 공유 싱글톤 개체의 상태가
손실 될 수 있습니다.
사례 1: (.NET 코드)
using System;
namespace SingletonSample
{
class Program
{
static void Main(string[] args)
{
//创建四个LoadBalancer对象
LoadBalancer balancer1,balancer2,balancer3,balancer4;
balancer1 = LoadBalancer.GetLoadBalancer();
balancer2 = LoadBalancer.GetLoadBalancer();
balancer3 = LoadBalancer.GetLoadBalancer();
balancer4 = LoadBalancer.GetLoadBalancer();
//判断服务器负载均衡器是否相同
if (balancer1 == balancer2 && balancer2 == balancer3 && balancer3 == balancer4)
{
Console.WriteLine("服务器负载均衡器具有唯一性!");
}
//增加服务器
balancer1.AddServer("Server 1");
balancer1.AddServer("Server 2");
balancer1.AddServer("Server 3");
balancer1.AddServer("Server 4");
//模拟客户端请求的分发,如果输出结果全为同一个server,可以将i适当放大,例如改为"i < 100"
for (int i = 0; i < 10; i++)
{
string server = balancer1.GetServer();
Console.WriteLine("分发请求至服务器: " + server);
}
Console.Read();
}
}
}
using System;
using System.Collections;
namespace SingletonSample
{
class LoadBalancer
{
//私有静态成员变量,存储唯一实例
private static LoadBalancer instance = null;
//服务器集合
private ArrayList serverList = null;
//私有构造函数
private LoadBalancer()
{
serverList = new ArrayList();
}
//公有静态成员方法,返回唯一实例
public static LoadBalancer GetLoadBalancer()
{
if (instance == null)
{
instance = new LoadBalancer();
}
return instance;
}
//增加服务器
public void AddServer(string server)
{
serverList.Add(server);
}
//删除服务器
public void RemoveServer(string server)
{
serverList.Remove(server);
}
//使用Random类随机获取服务器
public string GetServer()
{
Random random = new Random();
int i = random.Next(serverList.Count);
return serverList[i].ToString();
}
}
}
사례 2: (JAVA 코드)
public class Singleton {
private static Singleton sing;
private Singleton() {
}
public static Singleton getInstance() {
if (sing == null) {
sing = new Singleton();
}
return sing;
}
}
public class Test {
public static void main(string[] args) {
Singleton sing = Singleton.getInstance();
Singleton sing2 = Singleton.getInstance();
System.out.println(sing);
System.out.println(sing2);
}
}