JAVA) 이 클래스 단비꺼야! 싱글톤 패턴이란

백준우·2022년 12월 29일
0

Java & Spring

목록 보기
5/6
post-thumbnail
post-custom-banner

1. 싱글톤 패턴

  1. 싱글톤 패턴이란?
  2. 예시코드

들어가면서

  • 저번에 클래스에 대해 공부를 하다가 그럼 항상 클래스를 만들어 사용하면 그것또한 메모리에 비용이 소비되지 않을까라는 생각을 했다.
  • 이러한 생각을 이미 고려한 JAVA는 싱글톤 패턴이란 방법을 이미 사용하고 있었다;;
  • 자주사용하지는 않을것 같지만 프로젝트를 진행하면서 자주쓰이는 클래스는 인스턴스로 무분별한 남발보단 싱글톤 패턴을 고려해 봐야겠다.

1. 추상클래스

  1. 싱글톤 패턴이란?
    1) 어떠한 클래스가 최초한번만 메모리에 할당되고 그 메모리를 인스턴스로 만들어 재사용할 수 있는 패턴이다.
    2) 하나의 인스턴스를 메모리에 등록하고 여러쓰리드에서 동시에 공유해서 사용할 수 있는 방법이다.
    3) 주희할 점은 싱글톤 패턴을 만들땐 동시성에대해 주의를 고려해야한다.

    • 싱글톤 패턴의 장점
      1) 고정된 메모리 영역을 얻으면서 한번의 new 인스턴스만 사용하기 떄문에 메모리 낭비를 방지할 수 있다. / 인스턴스 생성시간을 줄일 수 있다.
      2) 싱글톤 패턴으로 만들어진 인스턴스는 전역이기 때문에 다른 클래스인 인스턴스들과 데이터 공유가 쉽다.
      3) 인스턴스가 한개만 존재하는것을 보증할 수 있다.

    • 싱글톤 패턴의 단점
      1) 싱글톤 패턴을 구현하려면 코드자체가 많이 필요하다.
      2) 테스트가 힘들다. / 데이터를 공유하기 때문에 격리된 환경에서 수행되는 테스트가 온전히 수행되긴 힘들다
      3) 자식클래스를 만들 수 없고, 메서드를 수정하는 등이 제한되어 유연성이 많이 떨어진다.
  2. 예시코드

// 싱글톤 패턴 객체 선언
public class Car {
	
    private static Car instance;
    
	private Car() { } // 생성자를 private로 선언해서 외부의 접근을 제한한다.
	
    public static Car getInstance() {
    	if(instance == null) {
        	instance = new Car(); // instance가 없으면 static으로 Car를 선언한다.
        }
    	return instance; // 외부에서 클래스에 접근할 수 있는 getInstance메서드를 만든다. 
    }
    
    public void say() {
    	System.out.println("test Single");
    }
}

// 싱글톤 패턴 접근 
public class Test {
   public static void main(String[] args) {
          Car singleton1 = Car.getInstance();
          Car singleton2 = Car.getInstance();

          System.out.println(singleton1); // ch01.Car@5eb5c224
          System.out.println(singleton2); // ch01.Car@5eb5c224
      }
}

TIP ) 싱글톤패턴을 사용할때 데이터의 일관성의 문제란?

// 싱글톤 패턴 객체 선언
public class Car {
	
    private static Car instance;
   	private static int num = 0; // 안에 변수를 설정하게 될경우 
    
	private Car() { } // 생성자를 private로 선언해서 외부의 접근을 제한한다.
	
    public static Car getInstance() {
    	if(instance == null) {
        	instance = new Car(); // instance가 없으면 static으로 Car를 선언한다.
        }
    	return instance; // 외부에서 클래스에 접근할 수 있는 getInstance메서드를 만든다. 
    }
    
    public void count() {
    	 num++;
    }
}

외부에서 각기다른 스레드에서 위 count메소드를 사용하면 num의 데이터가 일관성있게 흘러가지 않는다.
위의 방법을 해결하기 위해선 2가지 방법을 적용할 수 있다.

  • 정적 변수선언에서 인스턴스 생성
public class Car {
	
    private static Car instance = new Car(); // 초기에 인스턴스를 생성하게 된다면 다른 객체들은 getInstance를 통해 하나의 인스턴스를 공유할 수 있다.
    
	private Car() { } // 생성자를 private로 선언해서 외부의 접근을 제한한다.
	
    public static Car getInstance() {
    	return instance; // 외부에서 클래스에 접근할 수 있는 getInstance메서드를 만든다. 
    }
    
    public void say() {
    	System.out.println("test Single");
    }
}
  • synchrozied의 사용
public class Car {
	
    private static Car instance; 
    
	private Car() { } // 생성자를 private로 선언해서 외부의 접근을 제한한다.
	
    public static synchronzied Car getInstance() { // synchronzied를 적용하면 해결이 되지만 해당 방법은 성능 저하가 발생할 것이다.
    	if(instance == null) {
        	instance = new Car(); 
        }
    	return instance; // 외부에서 클래스에 접근할 수 있는 getInstance메서드를 만든다. 
    }
    
    public void say() {
    	System.out.println("test Single");
    }
}

마치며 ...

  • 싱글톤 패턴은 메모리, 속도, 데이터 공유 측면에서 이점이 있다.
  • 확실히 메모리절약은 되겠지만 아무래도 유연성이 제한되기 때문에 코드를 작성할땐 아무래도 어려울거 같아 보였다.
  • 메모리가 많이 들어가는 메소들중에 데이터를 소유하지않는 클래스들의 경우 싱글톤 패턴을 적용하면 유용할거 같다.

참고

profile
이게 되네?
post-custom-banner

0개의 댓글