Home [Effective Java] Item 3
Post
Cancel

[Effective Java] Item 3

Effective Java - Item 3

❓ μ‹±κΈ€ν„΄(singleton)

객체의 μœ μΌμ„±μ„ 보μž₯ν•˜κΈ° μœ„ν•΄μ„œ μΈμŠ€ν„΄μŠ€λ₯Ό 였직 ν•˜λ‚˜λ§Œ 생성할 수 μžˆλŠ” νŒ¨ν„΄μ„ μ˜λ―Έν•œλ‹€.

일반적으둜 μ‹±κΈ€ν„΄ 객체에 λŒ€ν•œ μ°Έμ‘°λ₯Ό public static ν•„λ“œλ‚˜ public static λ©”μ„œλ“œλ‘œ λ…ΈμΆœν•˜κΈ° λ•Œλ¬Έμ— μ–΄λ””μ—μ„œλ‚˜ μ‹±κΈ€ν„΄ 객체 접근이 κ°€λŠ₯ν•˜λ‹€.

μ‹±κΈ€ν„΄ νŒ¨ν„΄μ„ ν™œμš©ν•˜λ©΄ 객체λ₯Ό μž¬μ‚¬μš© ν•  수 있기 λ•Œλ¬Έμ— λ©”λͺ¨λ¦¬ μ‚¬μš© λ‚­λΉ„λ₯Ό 막을 수 있고 μ „μ—­ 객체이기 λ•Œλ¬Έμ— λ‹€λ₯Έ 객체와도 순쑰둭게 κ³΅μœ κ°€ κ°€λŠ₯ν•˜λ‹€.

보톡 두 가지 방법을 μ‚¬μš©ν•˜μ—¬ 싱글턴을 μƒμ„±ν•œλ‹€. 첫 λ²ˆμ§ΈλŠ” public static 멀버λ₯Ό final둜 μ„ μ–Έν•˜μ—¬ μƒμ„±ν•˜λŠ” 방법이닀. λ˜ν•œ μ™ΈλΆ€μ—μ„œλŠ” μƒμ„±μžλ₯Ό 톡해 객체λ₯Ό 생성할 수 없도둝 μ ‘κ·Ό κΆŒν•œμ„ private둜 μ„ μ–Έν•΄μ•Όν•œλ‹€.

  • public static final ν•„λ“œ

    1
    2
    3
    4
    
      public class Singleton { 	 	
      	public static final Singleton INSTANCE = new Singleton(); 	 	
      	private Singleton() {}  
      } 
    

    β†’ 클래슀 μƒμ„±μ‹œμ— μΈμŠ€ν„΄μŠ€λ₯Ό λ”± ν•œ 번 μƒμ„±ν•œλ‹€.

    ν•΄λ‹Ή 방법은 ν΄λž˜μŠ€κ°€ μ‹±κΈ€ν„΄μž„μ„ λͺ…ν™•ν•˜κ²Œ μ•Œ 수 있고 κ°„κ²°ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆλ‹€λŠ” μž₯점을 가지고 μžˆλ‹€.

    λ‹€λ§Œ, λ¦¬ν”Œλ ‰μ…˜ APIλ₯Ό μ‚¬μš©ν•˜μ—¬ μ˜ˆμ™Έμ μœΌλ‘œ κ°•μ œλ‘œ μƒμ„±μžλ₯Ό 생성할 수 μžˆλŠ” 방법이 μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— 이λ₯Ό μ£Όμ˜ν•˜μ—¬ μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ•Ό ν•œλ‹€.

    πŸ‘‰ λ¦¬ν”Œλ ‰μ…˜ APIλ₯Ό μ‚¬μš©ν•˜μ—¬ μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  경우

    • μ½”λ“œ
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
      import java.lang.reflect.Constructor;
      import java.lang.reflect.InvocationTargetException;
        
      public class SingletonReflect {
        
      	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
      		Constructor<Singleton> declaredConstructor = Singleton.class.getDeclaredConstructor();
      		declaredConstructor.setAccessible(true);
        		
      		Singleton singleton = declaredConstructor.newInstance();
      	}
        
      }
    

    β†’ setAccessible(boolean)λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ Singleton 클래슀의 private μƒμ„±μžμ— 접근이 κ°€λŠ₯ν•˜λ‹€.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
      public class Singleton {
        	
      	public static final Singleton INSTANCE = new Singleton();
        	
      	private Singleton() {
      		if(INSTANCE != null) {
      			throw new UnsupportedOperationException("μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  수 μ—†μŠ΅λ‹ˆλ‹€.");
      		}
      	}
        
      }
    

    β†’ μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•˜μ—¬ μΈμŠ€ν„΄μŠ€κ°€ μ‘΄μž¬ν•  경우 μƒμ„±μž 호좜 λΆˆκ°€ν•˜λ„λ‘ λ§‰λŠ”λ‹€.

두 λ²ˆμ§ΈλŠ” μƒμ„±μžλŠ” private둜 μ„ μ–Έν•˜κ³  정적 νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό ν™œμš©ν•˜λŠ” 방법이닀.

  • μ½”λ“œ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {
	
	private static Singleton INSTANCE = new Singleton();
	
	private Singleton() {}
	
	public static Singleton getInstance() {
		if(INSTANCE == null) {
			INSTANCE = new Singleton();
		}
		return INSTANCE;
	}

}

β†’ 클래슀 μƒμ„±μ‹œμ— μΈμŠ€ν„΄μŠ€λ₯Ό λ”± ν•œλ²ˆλ§Œ μƒμ„±ν•œλ‹€. getInstance() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” κ²½μš°μ— 이미 μ‘΄μž¬ν•˜λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•΄μ£Όμ–΄ 항상 같은 객체의 μ°Έμ‘°λ₯Ό λ°˜ν™˜ν•œλ‹€.

정적 νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό ν™œμš©ν•œλ‹€λ©΄ 싱글턴이 μ•„λ‹ˆλ„λ‘ ν•˜κ³  싢을 λ•Œμ—λ„ APIλ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³ λ„ μ‰½κ²Œ λ‹€λ₯Έ 객체λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ λ³€κ²½ν•  수 μžˆλ‹€. λ˜ν•œ λ©”μ†Œλ“œ μ°Έμ‘°λ₯Ό κ³΅κΈ‰μžλ‘œ μ‚¬μš©ν•  수 있고(Singleton::getInstance), 정적 νŒ©ν† λ¦¬λ₯Ό μ œλ„€λ¦­ μ‹±κΈ€ν„΄ νŒ©ν† λ¦¬λ‘œ λ§Œλ“€ 수 μžˆλ‹€.

β“μ œλ„€λ¦­ μ‹±κΈ€ν„΄ νŒ©ν† λ¦¬

μ œλ„€λ¦­μœΌλ‘œ νƒ€μž…μ„€μ • κ°€λŠ₯ν•œ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄λ‘κ³ , λ°˜ν™˜ μ‹œμ— μ œλ„€λ¦­μœΌλ‘œ 받은 νƒ€μž…μ„ μ΄μš©ν•΄ νƒ€μž…μ„ κ²°μ •ν•˜λŠ” 것이닀.

ν•΄λ‹Ή 방법도 μ—­μ‹œ λ¦¬ν”Œλ ‰μ…˜ APIλ₯Ό μ‚¬μš©ν•˜μ—¬ κ°•μ œλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 있기 λ•Œλ¬Έμ— μ£Όμ˜κ°€ ν•„μš”ν•˜λ‹€.

public static ν•„λ“œλ‚˜ 정적 νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό ν™œμš©ν•˜μ—¬ μž‘μ„±ν•œ μ‹±κΈ€ν„΄ 클래슀λ₯Ό μ§λ ¬ν™”ν•˜λ €λ©΄ λ‹¨μˆœνžˆ Serializable을 κ΅¬ν˜„ν•˜κ³  μ„ μ–Έν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œλŠ” λΆ€μ‘±ν•˜λ‹€. λͺ¨λ“  μΈμŠ€ν„΄μŠ€ ν•„λ“œλ₯Ό μΌμ‹œμ (transient)이라고 μ„ μ–Έν•˜κ³  ReadResolve λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•΄μ•Όν•œλ‹€. 그렇지 μ•ŠμœΌλ©΄ μ—­μ§λ ¬ν™”μ‹œ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λ˜κΈ° λ•Œλ¬Έμ΄λ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ, Effective Javaμ—μ„œ μ‹±κΈ€ν„΄ νŒ¨ν„΄μ„ μƒμ„±ν•˜λŠ”λ° κ°€μž₯ 이상적인 λ°©λ²•μœΌλ‘œ μ•Œλ¦¬κ³  μžˆλŠ” Enum을 ν™œμš©ν•˜μ—¬ μ›μ†Œκ°€ ν•˜λ‚˜μΈ μ—΄κ±° νƒ€μž…μ„ μ„ μ–Έν•˜λŠ” 방법이 μ‘΄μž¬ν•œλ‹€.

1
2
3
public enum SingletonEnum {
	INSTANCE;
}

❓ Enum

클래슀처럼 보이게 ν•˜λŠ” μƒμˆ˜μ΄λ©°, μ„œλ‘œ κ΄€λ ¨μžˆλŠ” μƒμˆ˜λ“€λΌλ¦¬ λͺ¨μ•„ μƒμˆ˜λ“€μ„ μ •μ˜ν•  수 μžˆλ‹€.

ν•΄λ‹Ή 방법은 κ°„κ²°ν•˜κ²Œ μž‘μ„±ν•  수 μžˆμ„λΏλ”λŸ¬ μ–΄λ– ν•œ λ°©μ‹μ—μ„œλ„ μΈμŠ€ν„΄μŠ€κ°€ μΆ”κ°€λ‘œ μƒμ„±λ˜λŠ” 것을 막을 수 μžˆλ‹€. 또 직렬화λ₯Ό μœ„ν•΄ 좔가적인 μ½”λ“œλ₯Ό μž‘μ„±ν•  ν•„μš”κ°€ μ—†κΈ° λ•Œλ¬Έμ— μ‹±κΈ€ν„΄ 객체λ₯Ό 생성할 λ•Œμ—λŠ” Enum을 ν™œμš©ν•˜λŠ” 방법을 κ°€μž₯ 쒋은 방법이라고 말할 수 μžˆλ‹€.

This post is licensed under CC BY 4.0 by the author.

[Effective Java] Item 2

[Effective Java] Item 4