달력

1

« 2021/1 »

  •  
  •  
  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
  •  
  •  
  •  
  •  

'Design Pattern'에 해당되는 글 1

  1. 2011.01.05 Singleton Pattern
2011. 1. 5. 14:31

Singleton Pattern Design Pattern2011. 1. 5. 14:31

Application 이 실행되는 동안 단 1개의 Instance 만을 사용하고 싶을 때 사용하는 방법이 있다.
보통은 이걸 Singleton Pattern 이라고 하는데, 코드는 아래와 같다. 코드는 계속 개선된다.
Singleton 방식으로 관리할 클래스의 이름은 Context 라는 클래스라고 가정하자


public class Context {

  private static Context context;

  //다른 클래스에서 new Context() 를 이용한 Context 클래스의 인스턴스 생성을 막는다.
  private Context() { } 
  public static Context getInstance() {
    if(context == null) {
      context = new Context();
    } // end if
    return context;
  } // end getInstance()
}

위와 같은 Singleton 설계방법에는 위험성이 따르게 된다.
Multi-Thread 환경에서 객체를 2개 이상 만들어버릴 수 있기 때문이다. 
어제까지, 이에대한 해결책은 3가지 정도만 있다고 알고 있었다.

1. private static Context context = new Context();
   단점 : 쓸데없는 메모리를 차지하게 될 수 있다는 단점이 있다.

2. synchronized 키워드를 이용해서 동기화를 시키는 방법이 있다.
   2-1. synchronized 를 이용해서 getInstance() 메소드 자체를 동시화 시킨다.
        public static Context getInstance() -> public static synchronized Context getInstance()
        해당 메소드에 대해서 성능면에서 '심각한' 손해가 있다고 한다.
   2-2. DCL (Double Checked-Locking) 기법을 사용한다.
        인스턴스 생성을 인스턴스가 필요한 시점까지 최대한 늦출수 있다. 1번의 단점은 해소된다.
        처음 객체를 만들때만 동기화가 된다. 2번의 단점도 어느정도 해소시킬수 있다.
        자세한 방법은, volatile(이 키워드가 생소하다면 여기 를 참조) 키워드를 레퍼런스 변수에 걸어둔다.
        
        private volatile static Context context; <-- 와 같이 선언한 후에,
        
        public static Context getInstance() {
          if(context == null) {
            synchronized(Context.class) {
              if(context == null) {
                context = new Context();
              } // end if
            } // synchronized block
          } // end if
          return context;
        } // end getInstance()
        
        적느라 힘들었음.ㅠ; 
        위와같은 코드를 getInstance 에 대체시키면, 객체를 만들때만 동기화 시키므로 하나의
        객체만 만들어서 관리한다는 설계의도에 빗나가지 않으며, 이후에는 동기화가 필요없게 된다.
        하지만 단점이 있다. volatile 키워드가 1.5 아래버전들에서는 완벽한 작동을 보장하지 않는다.


나는 여기까지가 전부인줄 알고 장단점을 고려해서 '돌려막기' 식으로 하면 되겠지 라는 생각을 했고,
어제 nhn i&s 신입 면접에서 마치 DCL 기법까지가 전부인것처럼 말했다. (ㅠㅠ)

하지만 오늘 인터넷을 검색해다가 보니, 다른 방법이 있었다. 
synchronized 키워드를 사용하지도 않고, java 버전에 구애되지도 않는 기법이다.
내부에 클래스를 하나 더 선언하면 된다고 한다.
구체적인 구현 코드는 아래와 같다.

public class Context {

 
private Context() {
  }

  private static class SingletonHolder {
   
private static final Context INSTANCE = new Context();
 
}
 
  public static Context getInstance() {
    return SingletonHolder.INSTANCE;
  }
}

.... olleh!! ㅠㅠ
왜 하필 이런건 면접본 다음날 알게되는것인가!! OTL....
내가 부족한탓이라고 생각하고 공부를 멈추지 말아야 하겠다...
.. 그런데 토익점수 없는 나오서는 더이상 서류통과 되는곳이 없을까봐 두렵다...-_-;

Posted by maruldy

댓글을 달아 주세요