java/oop

[oop] 12. 싱글톤(Singleton) 클래스

jeri 2024. 4. 19. 13:16
반응형

1. 싱글톤(Singleton)클래스의 개념

  • 싱글톤 디자인 패턴을 적용하여 작성된 클래스
  • 상속성의 개념을 무시하고 만들어짐
    • 왜? 기본생성자가 은닉화되어있으니까!!
    • 그래서 고급자바에서는 싱글톤클래스를 사용하긴 하지만 다른 형태로 모델링해서 만듦
  • 사실 싱글톤클래스로 만들지 않아도 프로그램 만드는 데에 상관은 없지만 싱글톤으로 제공해주면 불필요한 객체가 여러개 만들어지는 것 방지 가능함

 

 

2. 싱글톤클래스를 만드는 목적

  • 싱글톤으로 제공해주면 불필요한 객체가 여러개 만들어지는 것 방지 가능!
  • 프로그램에 객체를 딱 하나만 제공하기 위한 목적의 클래스를 작성하기 위해 사용한다.
  • 데이터처리클래스에서 많이 사용 → 객체 하나만 생성해 이용
  • ex. 값을 처리하기 위한 클래스는 값 만을 처리하므로 객체를 여러개 만들면 오히려 비효율적

디자인 패턴이란?

  • 기존 환경 내에서 반복적으로 일어나는 문제들을 어떻게 풀어나갈 것인가에 대한 일종의 솔루션 같은 것
  • 고급스러운 자바를 위한다면 공부 필요 ( 👍헤드퍼스트 디자인패턴 책 추천!)
    • 프로그램을 만드는 일종의 방법론
    • 이렇게 만드는 것이 더 효율적입니다!! 의 책

 

 

 

3. 싱글톤 클래스 만들기

[STEP1] private static 필드 선언

  • 클래스의 객체를 저장하기 위한 시스템 필드 선언 - 🔐private
  • static 지정자를 사용하여 정적 필드로 선언
    • 시스템 필드
      • 클래스 내부에서만 사용될 값을 저장하기 위한 필드
      • Getter 메소드와 Setter 메소드를 선언하지 않는 필드
      • 일반적인 필드와 구분하기 위해 필드명을 _로 시작되도록 작성하는 것을 권장
private static Singleton _instance;

[STEP2]  private 생성자 선언

  • 생성자를 은닉화 선언
  • 싱글톤클래스의 핵심🔥
  • 클래스 외부에서 생성자에 접근하지 못하도록 설정 : 객체 생성 불가능
	private Singleton() {
		// TODO Auto-generated constructor stub
	}

[STEP3]  정적 영역 안에 객체 생성

  • 정적 영역(Static Block)
    • 클래스가 메모리에 생성된 후 자동으로 실행될 명령을 작성하는 영역
    • 프로그램에서 한번만 실행되는 명령
    • 정적 필드 또는 정적 메소드만 사용 가능
	static {
		//클래스로 객체를 생성하여 시스템 필드에 저장 - 프로그램에서 하나의 객체만 생성하여 사용
		_instance=new Singleton();
	}

[STEP4]  정적메소드 선언

  • 미리 생성되어 시스템 필드에 저장된 객체를 반환하는 정적 메소드 선언 - getInstace()
	public static Singleton getInstace() {
		return _instance;
	}
  • 사용은?
Singleton.getInstace();

 

 

 

 

 

4. 싱글톤 클래스 사용하기

oop > Singleton.java
package oop;

public class Singleton {

	private static Singleton _instance;
	
	private Singleton() {
		// TODO Auto-generated constructor stub
	}
	
	static {
		_instance=new Singleton();
	}
	
	public static Singleton getInstace() {
		return _instance;
	}
	
	//인스턴스 메소드
	public void display() {
		System.out.println("Singleton 클래스의 display() 메소드 호출");
	}
}
oop > SingletonApp.java
package oop;

public class SingletonApp {
	public static void main(String[] args) {

		/*
		//방법1. 비권장 
    	//(생성자 - 🔐public일 경우)
		//new 연산자로 생성자를 호출하여 객체 생성 - 객체를 여러 개 생성하여 사용 가능
		// => 생성된 객체를 참조변수에 저장하여 참조변수에 객체를 참조하여 메소드 호출
		Singleton singleton1=new Singleton();
		Singleton singleton2=new Singleton();
		System.out.println("singleton1 = "+singleton1);  //singleton1 = oop.Singleton@5aaa6d82
		System.out.println("singleton2 = "+singleton2);  //singleton2 = oop.Singleton@5abcdd23
		singleton1.display();
		singleton2.display();
		*/

		//방법1. 비권장
		//(생성자 - 🔐private일 경우)
		//싱글톤 클래스는 생성자가 은닉화 선언되어 new 연산자로 객체 생성 불가능
		//Singleton singleton=new Singleton(); //error
		//클래스 생성시 미리 생성되어 시스템 필드에 저장된 객체를 반환하는 정적 메소드 호출 - 프로그램에서 객체를 하나만 제공받아 사용
		Singleton singleton1=Singleton.getInstace();
		Singleton singleton2=Singleton.getInstace();
		System.out.println("singleton1 = "+singleton1); //singleton1 = oop.Singleton@5aaa6d82
		System.out.println("singleton2 = "+singleton2); //singleton2 = oop.Singleton@5aaa6d82
		singleton1.display();
		singleton2.display();

		//방법2. 권장
		//싱글톤 클래스는 참조변수에 객체를 저장하여 참조변수로 메소드를 호출하지 않고 객체를 반환받아 메소드를 직접 호출하여 사용하는 것을 권장
		Singleton.getInstace().display();

	}
}

 

 

VO클래스
데이타(값)를 저장하기 위한 객체를 여러개 만들기 위해

싱글톤클래스
불필요한 객체가 여러개 만들어지는 것을 방지 하기 위해

 

 

 

 

5. Runtime클래스 사용하기

oop > RuntimeApp.java
  • java.base 모듈 >> java.lang 패키지 >> Runtime 클래스 >> static getRuntime()메소드
  • Runtime의 유일한static메소드 - 우리가 접근가능
package oop;

public class RuntimeApp {
	public static void main(String[] args) {
    
		// Runtime클래스
        // => Java 프로그램을 실행하는 JVM 관련 정보를 저장하기 위한 클래스
		// => 생성자가 은닉화 선언되어 있어 new 연산자로 객체 생성 불가능
        
        // 싱글톤 클래스(Singleton Class)
		// => 프로그램에 객체를 하나만 제공하기 위한 클래스
		// => 대표적인 싱글톤 클래스들 : System클래스 , Math클래스 , Runtime클래스
		// => 생성자가 은닉화 선언되어 있어 접근할 수 없기 때문에
        // => new 연산자로 객체 생성이 불가능하다!
		//Runtime runtime=new Runtime(); //new연산자 이용 불가능 - error
		
        
        
		// <runtime클래스(싱글톤클래스)로 객체 생성 하는 법>
		// => 프로그래머가 직접 객체를 만드는 것은 아니고 , 
        // => Runtime 객체를 반환하는 정적 메소드를 이용

		// Runtime.getRuntime()
        // => Runtime 객체를 반환하는 정적 메소드 - 클래스명으로 호출
		// => getRuntime() 메소드를 여러번 호출해도 같은 객체를 반환
		Runtime runtime1=Runtime.getRuntime();
		Runtime runtime2=Runtime.getRuntime();		
		System.out.println("runtime1 = "+runtime1); //runtime1 = java.lang.Runtime@7d6f77cc
		System.out.println("runtime2 = "+runtime2); //runtime2 = java.lang.Runtime@7d6f77cc
		System.out.println("runtime3 = "+runtime3); //runtime2 = java.lang.Runtime@7d6f77cc
	

		//Runtime.totalMemory() : JVM이 사용 가능한 전체 메모리의 크기(Byte)를 반환하는 메소드
		//Runtime.freeMemory() : JVM이 사용 가능한 여유 메모리의 크기(Byte)를 반환하는 메소드
		//System.out.println("청소 전 JVM 사용 메모리 크기 = "+(runtime1.totalMemory()-runtime1.freeMemory())+"Byte");

		//싱글톤 클래스는 객체를 반환받아 참조변수에 저장하여 메소드를 호출하지 않고 객체를 반환받아 직접 메소드를 호출하여 사용하는 것을 권장
		System.out.println("청소 전 JVM 사용 메모리 크기 = "+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())+"Byte");
		
		//자바에서는 참조변수 없이 객체를 호출할 수 있으면 그렇게 하는 것을 권장

		//Runtime.gc() : 메모리를 청소하는 가비지 콜렉터(Garbage Collector)를 실행하는 정적 메소드
		// => System.gc() 메소드로 동일한 기능 제공 가능 - 정적 메소드 
		//Runtime.getRuntime().gc();
		
		//사실 static영역, heap영역은 배열 및 객체가 자동소멸되지 않음 
		//하지만 JVM이 알아서 가비지콜렉터를 실행해 메모리를 청소해줌
		//Runtime.gc()메소드는 가비지 콜렉터를 프로그래머가 직접 실행해 여유공간 확보하는 것임

		System.out.println("청소 후 JVM 사용 메모리 크기 = "+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())+"Byte");
	}
}
반응형