백엔드/Java

Java 싱글톤 패턴(Singleton Pattern)

짱뚱짱 2024. 11. 15. 09:41

🔷 디자인 패턴

- 개발자들이 개발 과정에서 하나의 패턴으로 묶어놓은 코드 조합

- 소프트웨어 개발에서 자주 발생하는 문제를 해결하기 위한 효율적이고 재사용 가능한 솔루션

- 개발자들이 오랜 시간에 걸쳐 검증한 베스트 프랙티스를 코드로 묶어놓은 것

- https://refactoring.guru/ko/design-patterns 에서 다양한 디자인 패턴 확인 가능

 

🔷 싱글톤 패턴

- 디자인 패턴 중 하나로, 특정 클래스의 인스턴스오직 하나만 존재하도록 보장하는 패턴

- 즉, 단 1개만 존재해야 하는 객체를 생성하여 공유하고자 할 때 사용한다.

- 애플리케이션에서 전역적으로 공유되는 객체가 필요할 때 사용 => 애플리케이션 설정, 데이터베이스 연결, 로그 파일 관리 등

 

🔷 싱글톤 패턴 구현

싱글톤 패턴을 구현하려면 다음과 같은 사항들을 지켜야 한다.

  👉🏻 생성자를 private으로 설정하여 외부에서 인스턴스를 생성하지 못하게 함.

  👉🏻 static 메서드getInstance()를 통해 하나의 객체만 생성되도록 관리

class Singleton {

    // 단 1개만 존재하기 위해 객체의 인스턴스 생성 (공유)
    // 단 1개만 존재하는 객체를 위한 static 변수
    private static Singleton instance;

    // 생성자를 통해 객체 생성을 막기 위해 생성자를 private 설정
    // 생성자 private으로 설정하여 외부에서 인스턴스를 생성하지 못하게 함
    private Singleton() {}

    // getInstance() 메서드를 사용하여 instance를 생성 리턴
    // instance가 있으면 기존 instance를 리턴
    // instance가 없으면 새로 생성해서 리턴
    // getInstance()를 통해 하나의 객체만 생성하고 리턴
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();  // 객체가 없으면 생성
        }
        return instance;
    }
}

 

 

🔷 실습(1)

싱글톤 객체를 사용하여 같은 클래스의  단일 인스턴스가 여러 번 호출되어도 동일한 객체를 반환시킴.

public class Singleton01 {

    public static void main(String[] args) {
        // Singleton 객체 생성
        Singleton s = Singleton.getInstance();
        Singleton s1 = Singleton.getInstance();

        // 두 객체의 주소값이 같음 -> 하나의 인스턴스를 공유
        System.out.println(s);
        System.out.println(s1);
        
        Calendar c = Calendar.getInstance(); //캘린더도 싱글턴임.
		System.out.println(c);
		Calendar c1 = Calendar.getInstance();
		System.out.println(c1);
    }
}

 

 

결과

day11.Singleton@6a5fc7f7
day11.Singleton@6a5fc7f7
java.util.GregorianCalendar[time=1731493233008,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Seoul",offset=32400000,dstSavings=0,useDaylight=false,transitions=30,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2024,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=3,DAY_OF_MONTH=13,DAY_OF_YEAR=318,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=20,SECOND=33,MILLISECOND=8,ZONE_OFFSET=32400000,DST_OFFSET=0]
java.util.GregorianCalendar[time=1731493233023,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Seoul",offset=32400000,dstSavings=0,useDaylight=false,transitions=30,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2024,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=3,DAY_OF_MONTH=13,DAY_OF_YEAR=318,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=20,SECOND=33,MILLISECOND=23,ZONE_OFFSET=32400000,DST_OFFSET=0]

// s와 s1은 동일한 메모리 주소를 가리킴. => 하나의 인스턴스를 공유
// c와 c1도 마찬가지

 

 

🔷 실습(2)

- 싱글톤 패턴을 활용하여 특정 값 관리 가능

class Counter {
    // 싱글톤으로 생성
    private int count;
    // 내 객체를 저장하는 멤버변수(static)
    private static Counter instance;

    // 생성자 private
    private Counter() {}

    // getInstance()를 사용하여 인스턴스를 관리
    public static Counter getInstance() {
        if (instance == null) {
            instance = new Counter();
        }
        return instance;
    }

    // count가 하나 올라가는 메서드 생성
    public int countMethod() {
        count++;
        return this.count;
    }
}

public class Singleton02 {

    public static void main(String[] args) { 
        // Counter 객체 2개 생성하여 각각 countMethod() 호출
        // 1개의 객체가 공유되기 때문에 1개의 변수만 변화

        Counter c = Counter.getInstance();
        Counter c1 = Counter.getInstance();

        System.out.println("c > " + c.countMethod());  // 1
        System.out.println("c > " + c.countMethod());  // 2
        System.out.println("c > " + c.countMethod());  // 3

        System.out.println("c1 > " + c1.countMethod());  // 4
        System.out.println("c1 > " + c1.countMethod());  // 5
        System.out.println("c1 > " + c1.countMethod());  // 6
    }
}

 

 

결과

c > 1
c > 2
c > 3
c1 > 4
c1 > 5
c1 > 6

 

🔷 싱글톤 패턴의 장점

  1️⃣ 전역적 접근 : 싱글톤 객체는 애플리케이션 전체에서 공통된 객체로 사용할 수 있어, 여러 클래스에서 동일하나 인스턴스를 쉽게 공유

  2️⃣ 메모리 절약 : 객체가 단 하나만 생성되므로 불필요한 메모리 낭비 X

  3️⃣ 상태 유지 : 객체의 상태를 지속적으로 유지할 수 있어, 상태 기반의 동작을 관리하기 유용


"한 번만 존재하면 충분하다."

'백엔드 > Java' 카테고리의 다른 글

Java 네트워크(Network)  (0) 2024.11.14
Java 쓰레드(Thread)  (0) 2024.11.13
Java 파일 입출력 (I/O) 처리  (0) 2024.11.04
Java 스트림(Stream)  (0) 2024.10.30
Java 람다(Lambda)  (0) 2024.10.29