💡
싱글톤 패턴은 해당 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴입니다.
구현 원리
public class Singleton { 
    //1
    private static Singleton uniqueInstance;
    //2
    private Singleton() {}
    
    //3
    public static Singleton getInstance() { 
        if ( uniqueInstance == null ) { 
                uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}
Singleton 클래스의 유일한 인스턴스를 저장하기 위한 정적 변수입니다.
생성자를 private으로 선언했기 때문에 Singleton에서만 클래스의 인스턴스를 만들 수 있습니다.
getInstance() 메소드에서는 클래스의 인스턴스를 만들어서 리턴해줍니다.
uniqueInstance가 null이면 아직 인스턴스가 생성되지 않았다는 것을 의미합니다.
아직 인스턴스가 만들어지지 않았다면 private으로 선언된 생성자를 이용해서 Single 객체를 만든 다음 uniqueInstance에 그 객체를 대입합니다. 이렇게 하면 인스턴스가 필요한 상황이 닥치기 전에는 아예 인스턴스를 생성하지 않게 됩니다. 이런 방법을 "게으른 인스턴스 생성(lazy instantiatioin)"이라고 부릅니다.
문제점
(1) 인스턴스를 필요할 때 생성하지 말고, 처음부터 만들어 버립니다.
public class Singleton { 
    //1
    private static Singleton uniqueInstance = new Singleton()
    //2
    private Singleton() {}
    
    //3
    public static Singleton getInstance() { 
        return uniqueInstance;
    }
}
(2) getInstance()를 동기화시켜줍니다.
public class Singleton { 
    private static Singleton uniqueInstance;
    private Singleton() {}
    
    //1
    public static **synchronized** Singleton getInstance() { 
        if ( uniqueInstance == null ) { 
                uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}
(3)DCL(Double-Checing Locking)을 써서 getInstance()에서 동기화되는 부분을 줄입니다.
public class Singleton { 
    //1
    private static volatile Singleton uniqueInstance;
    private Singleton() {}
    
    public static Singleton getInstance() { 
        //2
        if ( uniqueInstance == null ) { 
                //3
                synchronized (Singleton.class) { 
                    if (uniqueInstance == null) { 
                            //4
                            uniqueInstance = new Singleton();
                    }
                }
        }
        return uniqueInstance;
    }
}
public class Singleton {
        //1
    private static let shared = Singleton()
    //2
    private init() {}
    //3
    public static func getInstance() -> Singleton {
        return shared
    }
    public func toString() {
        print("Singleton")
    }
}
Singleton.getInstance().toString()
---result---
Singleton