ㅇTL

Design pattern - Singleton 본문

2-1/객체지향 - java

Design pattern - Singleton

정노르레기 2022. 6. 13. 21:47

Design patter

= 소프트웨어 설계할 때 자주 발생하는 문제들에 재사용할 수 있는 훌륭한 해결책

= 가이드로 사용할 수 있는 모델 혹은 설계

=> 특정 상황에서 일반적인 문제에 대한 입증된 솔루션 !

 

- 이미 해결된 문제를 처리하기 위한 툴킷을 제공

- 소프트웨어 문제를 어떻게 해결할지 생각하는데 도움을 줌

 

- 23개의 디자인 패턴을 정리하고, 다음 3가지로 분류함

1. Creational(생성) : 객체 생성과 관련된 패턴

2. Structural(구조) : 클래스나 객체를 조합해 더 큰 구조를 만드는 패턴

3. Behavioral(행위) : 객체나 클래스 사이의 알고리즘이나, 책임 분재에 관련된 패턴 


Singleton

= 한 클래스에 대해 객체를 하나만 !! 생성할 수 있도록 한 것 -> 어디서든지 사용 가능

1. constructor은 private으로 해서 생성할 수 없게 하고, (-> 클래스 내부에서만 클래스의 인스턴스 생성 가능)

2. 멤버변수로 해당 클래스 객체를 static으로 가진다

3. 그리고 객체가 null일때 객체 만드는 static 함수 만들어서 해당 객체 한번만 생성될 수 있도록 한다 !

 

: 전역변수를 사용하지 않고 객체를 하나만 생성하도록 하며, 이 객체 어디서든지 참조할 수 있도록 하는 패턴 !

-> 단 하나의 인스턴스를 생성해 (전역변수처럼) 사용하는 디자인 패턴

사용예시 : 로그인, 캐시, 레지스터리 처리 객체.. 

 

장점

- 메모리 낭비 방지 가능

- 다른 클래스와 데이터 공유 편하게 가능

단점

- 기능 검증 및 수정이 어렵

- MultiThreading 환경에서 동기화처리 하지않으면 문제 발생 가능

 

예시

public class Logger{
	private static Logger instance; // 하나만 정적으로 만듬

    private Logger() P{} // 생성자는 private !!
    
    public static Logger getInstance(){ //static변수에 대한 함수이므로 static !
    	if(instance==null) //아무것도 없을때만 !!
        	instance=new Logger();
            
        return instance;
}

(-> 객체가 필요한 상황이 되기 전까지는 객체를 생성하지 xx)

 

 **문제점** 

: 여러 쓰레드가 동시에 접근할 때 문제가 생긴다!

저기서는 

if(instance=null)여기서 조건문이 동시에 두번 돌 수 있기때문에 하나의 인스턴스가 아닌 여러개의 인스턴스가 발생 할 위험이 있다 !.

 

 **해결 방법** 

1. Simple Locking

: synchronized를 사용하여 간단히 getInstance() 메소드를 Lock하는 방법

//1. 함수에 synchronized 쓴다
 public static synchronized Logger getInstance(){ 
    if(instance==null) //아무것도 없을때만 !!
       	instance=new Logger();
          
    return instance;
}

//2. 그 부분에만 동기화 씌운다
 public static Logger getInstance(){ 
 	synchonized(Logger.class){
    	if(instance==null) //아무것도 없을때만 !!
        	instance=new Logger();
    }    
        return instance;
}

!! synchronized(Classname.class){ 씌울 부분 } !!

 

* https://jgrammer.tistory.com/entry/Java-혼동되는-synchronized-동기화-정리

 

 

[Java] 혼동되는 synchronized 동기화 정리

synchronized는 lock을 사용해 동기화를 시킨다. 하지만 사용 방식에 따라 혼동되기 쉽다. synchronized는 4가지의 사용법이 있다. sychronized method, sychronized block, static sychronized method, static sy..

jgrammer.tistory.com

 

2. Double-Checked Locking

: volatile을 사용하여 Lock

//함수 안에..
if(instance==null{
	synchonized(Logger.class){
    	if(instance==null) //아무것도 없을때만 !!
        	instance=new Logger();
    }   
}

// 그리고 변수는 이렇게 선언
private volatile static Logger instance;

- null 을 두번물어본다 (double check) -> 두번째꺼에만 synchronized를 걸어준다

- 변수에 volatile를 적는다 (필수) ; 일단 간략하게 설명하자면 main memory가 있고 각 스레드 마다 working memory가 있다. main memory <-> working memory 이렇게 두 메모리간 데이터 이동이 있으며, 두 메모리간 동기화가 진행되는 동안 빈틈이 생기게 되기 때문에 volatile을 쓰는 것이다.

volatile 키워드 없이 DCL을 구현하면 생성이 되다만 객체를 다른 스레드에서 참조 할 수 있는 문제가 있다.

!! private volatile static !!

각 스레드가 동작하며 값을 메인메모리에서 읽어와서 cpu cache에 저장한다 

이때 변수 값 불일치 문제가 생길 수 있다

volatie은 변수를 main memory에 저장하겠다는 걸 명시하기 위해 사용한다

리드 거기서하고 라이트할때도 메인메모리에 작성한다

 

3. Eager Initialization

: 클래스 참조 시, 객체를 생성하여 충돌 방지하는 방법

= Class를 최초로 참조할 때 static변수이므로 자동으로 변수가 생김! (이거말고는 객체 생성 방법 xx)

public class Singleton{
	private Singleton(){ }
    private static Singleton instance = new Singleton();
    ~~
    public static Singleton getInstance(){
    	return instance;
    }
}

걍 변수 생성할 때 바로 초기화 해버리는것!

- class가 참조될 때 바로 객체를 생성하기 때문에 오버헤드가 작다.

-문제는 클라이언트가 사용하지 않더라도 무조건 생성된다는 점

'2-1 > 객체지향 - java' 카테고리의 다른 글

14. Collections, Maps, Iterators  (0) 2022.06.19
디자인패턴 2 - Observer & Decorator  (0) 2022.06.18
14- ArrayList , Generics  (0) 2022.06.13
Interfaces and Inner Classes  (0) 2022.06.02
19- Threads  (0) 2022.05.31