[μ΄νŽ™ν‹°λΈŒ μžλ°”] Item5. μžμ›μ„ 직접 λͺ…μ‹œν•˜μ§€ 말고 의쑴 객체 μ£Όμž…μ„ μ‚¬μš©ν•˜λΌ.

2023. 1. 12. 09:42ㆍJAVA/Effective JAVA

728x90

 

item05. μžμ›μ„ 직접 λͺ…μ‹œν•˜μ§€ 말고 의쑴 객체 μ£Όμž…μ„ μ‚¬μš©ν•˜λΌ. 

ν΄λž˜μŠ€κ°€ λ‚΄λΆ€μ μœΌλ‘œ ν•˜λ‚˜ μ΄μƒμ˜ μžμ›μ— μ˜μ‘΄ν•˜κ³ , κ·Έ μžμ›μ΄ 클래슀의 λ™μž‘μ— 영ν–₯을 μ€€λ‹€λ©΄ 정적 μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€λ‚˜ 싱글톀 방식이 μ ν•©ν•˜μ§€ μ•Šλ‹€. 

 

λ§Žμ€ ν΄λž˜μŠ€κ°€ ν•˜λ‚˜ μ΄μƒμ˜ μžμ›μ— μ˜μ‘΄ν•˜λŠ”λ° μ±…μ—μ„œ μ˜ˆμ œλ‘œλŠ” λ§žμΆ€λ²• 검사기λ₯Ό 예둜 λ“€κ³  μžˆλ‹€. 

λ§žμΆ€λ²• κ²€μ‚¬κΈ°λŠ” Dictionary에 μ˜μ‘΄ν•œλ‹€κ³  κ°€μ •ν•œλ‹€. 

 

1) 정적 μœ ν‹Έλ¦¬ν‹° 클래슀

public class SpellChecker
{
   // μžμ›μ„ 직접 λͺ…μ‹œν•œ μ½”λ“œ (μžμ›μ„ 직접 μƒμ„±ν•œλ‹€, new 둜 생성 )
   private static final Dictionary dictionary = new Dictionary();
   
   private SpellChecker()
   {
   
   }
   
   public static boolean isValid(String word)
   {
      return dictionary.contains(word);
   }
   
   public static List<String> suggestions(String typo)
   {
      return dictionary.closeWordsTo(typo);
   }
}

-> 정적 μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€λŠ” μžμ›μ„ 직접 μƒμ„±ν•΄μ„œ μ‚¬μš©ν•˜κ³  μžˆλŠ”λ° μ΄λ ‡κ²Œ μ‚¬μš©ν•˜λ©΄ μœ μ—°μ„±κ³Ό μž¬μ‚¬μš©μ„±μ΄ 떨어지고, ν…ŒμŠ€νŠΈν•˜κΈ° μ–΄λ ΅λ‹€. 

μ§€κΈˆμ€ Dictionaryν΄λž˜μŠ€κ°€ κ°„λ‹¨ν•˜μ§€λ§Œ 예λ₯Ό λ“€μ–΄ 이 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ”κ²Œ μžμ› μ†Œλͺ¨κ°€ λ§Žλ‹€κ³  κ°€μ •ν•˜μž. 

그러면 ν…ŒμŠ€νŠΈλ₯Ό ν•  λ•Œ μ§€κΈˆμ€ SpellChecker의 κΈ°λŠ₯에 λŒ€ν•΄μ„œλ§Œ ν…ŒμŠ€νŠΈ ν•˜κ³  μ‹Άμ§€λ§Œ 이 κΈ°λŠ₯을 ν…ŒμŠ€νŠΈ ν•˜κΈ° μœ„ν•΄μ„œλŠ” Dictionary 클래슀λ₯Ό μƒμ„±ν•΄μ„œ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€. μ΄λ ‡κ²Œ 되면 ν…ŒμŠ€νŠΈ ν•˜λŠ”λ° μ–΄λ €μ›Œμ§„λ‹€. 

 

그리고 μž¬μ‚¬μš©μ„±μ— λŒ€ν•΄μ„œ μƒκ°ν•˜λ©΄ μ§€κΈˆμ€ Dictionary인데 λ§Œμ•½ ν•œκΈ€ λ§žμΆ€λ²•μ— λŒ€ν•΄μ„œ κ²€μ‚¬ν•˜κ³  μ‹Άλ‹€~ ν•˜λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Όν•˜λŠ”κ°€..? 

ν•œκΈ€ 말고 μ˜μ–΄λ‘œ ν•  λ•ŒλŠ”? 그럴 λ•Œ λ§ˆλ‹€ 계속 μƒˆλ‘œμš΄ SpellChekcerλ₯Ό λ§Œλ“œλŠ”κ±΄ ꡉμž₯히 λΉ„νš¨μœ¨μ μ΄λ‹€. 

 

 

2) 싱글톀 방식

정적 μœ ν‹Έλ¦¬ν‹° 방법 λ§κ³ λŠ” 싱글톀 방식이 μžˆλ‹€. 

public class SpellChecker
{
   private final Dictionary dictionary = new Dictionary();
   
   private SpellChecker()
   {
   
   }
   
   public static final SpellChecker INSTANCE = new SpellChecker();
   
   public boolean isValid(String word)
   {
      return dictionary.contains(word);
   }
   
   public List<String> suggestions(String typo)
   {
      return dictionary.closeWordsTo(typo);
   }
}

-> 이 방식 μ—­μ‹œ μžμ›μ„ 직접 λͺ…μ‹œν•΄μ£Όκ³  있기 λ•Œλ¬Έμ— μž¬μ‚¬μš©μ„±, μœ μ—°μ„±μ΄ 떨어지고, ν…ŒμŠ€νŠΈν•˜κΈ° μ–΄λ ΅λ‹€. 

 

 

πŸ“’ 1) κ³Ό 2) 방식 λͺ¨λ‘ 사전을 ν•˜λ‚˜λ§Œ μ‚¬μš©ν•  수 밖에 μ—†κΈ° λ•Œλ¬Έμ— 쒋은 방법이 μ•„λ‹ˆλ‹€. 

μ‹€μ œλ‘œλŠ” 사전은 μ–Έμ–΄λ³„λ‘œ μ‘΄μž¬ν•˜κ³  있고 특수 μ–΄νœ˜μš© μ‚¬μ „μ΄λ‚˜ ν…ŒμŠ€νŠΈ 사전이 ν•„μš”ν•œ κ²½μš°λ„ μžˆλŠ”λ° 사전 ν•˜λ‚˜λ‘œ 이 λͺ¨λ“ κ²ƒμ„ λŒ€μ‘ν•˜κΈ°λŠ” μ–΄λ ΅λ‹€. 

 

즉, μ‚¬μš©ν•˜λŠ” μžμ›μ— 따라 λ™μž‘μ΄ λ‹¬λΌμ§€λŠ” ν΄λž˜μŠ€μ—λŠ” 정적 μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€λ‚˜ μ‹±κΈ€ν„΄ 방식이 μ ν•©ν•˜μ§€ μ•Šλ‹€. 

 

 

3) 의쑴 객체 μ£Όμž… 

1)κ³Ό 2) 방법 λŒ€μ‹ μ— SpellCheckerκ°€ μ—¬λŸ¬ μžμ› μΈμŠ€ν„΄μŠ€λ₯Ό 지원해야 ν•˜κ³ , ν΄λΌμ΄μ–ΈνŠΈκ°€ μ›ν•˜λŠ” μžμ›(Dictionary)을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€. 

이 방법이 λ°”λ‘œ 의쑴 객체 μ£Όμž…μœΌλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ μƒμ„±μžμ— ν•„μš”ν•œ μžμ›μ„ λ„˜κ²¨μ£ΌλŠ” 방식이닀. 

public class SpellChecker
{
   private final Dictionary dictionary;
   
   // μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ ν•„μš”ν•œ μžμ›μ„ λ„˜κ²¨μ£ΌλŠ” 방식
   public SpellChecker(Dictionary dictionary )
   {
      this.dictionary = dictionary;
   }
   
   public boolean isValid(String word)
   {
      return dictionary.contains(word);
   }
   
   public List<String> suggestions(String typo)
   {
      return dictionary.closeWordsTo(typo);
   }
}

-> μ΄λ ‡κ²Œ μ‚¬μš©ν•˜λ©΄ Dictionary λΌλŠ” λ”± ν•˜λ‚˜μ˜ 객체λ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ μžμ›μ΄ λͺ‡κ°œλ“  의쑴 관계가 μ–΄λ–»λ“  상관없이 잘 λ™μž‘ν•œλ‹€. 

 

 

 

πŸ™Œ νŒ©ν„°λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄ 

μœ„μ˜ 방법에 λ³€ν˜•μœΌλ‘œλŠ” μƒμ„±μžμ— μžμ› νŒ©ν† λ¦¬λ₯Ό λ„˜κ²¨μ£ΌλŠ” 방식이 μžˆλ‹€. 

νŒ©ν„°λ¦¬λž€ ν˜ΈμΆœν•  λ•Œ λ§ˆλ‹€ νŠΉμ • νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜λ³΅ν•΄μ„œ λ§Œλ“€μ–΄μ£ΌλŠ” 객체λ₯Ό λ§ν•œλ‹€. 

public class SpellChecker
{
   private final Dictionary dictionary;
   
   public SpellChecker(DictionaryFactory dictionaryFactory)
   {
      this.dictionary = dictionaryFactory.get();
   }
   
   public boolean isValid(String word)
   {
      return dictionary.contains(word);
   }
   
   public List<String> suggestions(String typo)
   {
      return dictionary.closeWordsTo(typo);
   }
}
public class DictionaryFactory
{
   public  Dictionary get()
   {
      return new DefaultDictionary();
   }

}

μ΄λ ‡κ²Œ νŒ©ν„°λ¦¬λ₯Ό μ‚¬μš©ν•΄μ„œ ν˜ΈμΆœν•  λ•Œ λ§ˆλ‹€ νŠΉμ • μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜λ³΅ν•΄μ„œ λ§Œλ“€μ–΄μ€„ μˆ˜λ„ μžˆλŠ”λ°, 

μ΄λ•Œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μΈ Supplierκ°€ νŒ©ν„°λ¦¬λ₯Ό ν‘œν˜„ν•œ μ™„λ²½ν•œ 예라고 ν•  수 μžˆλ‹€. 

[μ΄νŽ™ν‹°λΈŒ μžλ°”] Item03 μ™„λ²½κ³΅λž΅. ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ (tistory.com)

 

[μ΄νŽ™ν‹°λΈŒ μžλ°”] Item03 μ™„λ²½κ³΅λž΅. ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€

item03. private μƒμ„±μžλ‚˜ μ—΄κ±° νƒ€μž…μœΌλ‘œ μ‹±κΈ€ν†€μž„μ„ λ³΄μ¦ν•˜λΌ. " p24. Supplier, ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€" ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ Functional Interface λž€? : μžλ°”κ°€ μ œκ³΅ν•˜λŠ” κΈ°λ³Έ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ‘œ 1개의 좔상 λ©”

hyejin.tistory.com

Supplier<T>λŠ” 인자λ₯Ό 받지 μ•Šκ³  returnκ°’λ§Œ μ‘΄μž¬ν•˜λŠ” ν•¨μˆ˜μ΄λ‹€. (κ³΅κΈ‰μž μ—­ν• ) 

 

public class SpellChecker
{
   private final Dictionary dictionary;
   
   // μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ ν•„μš”ν•œ μžμ›μ„ λ„˜κ²¨μ£ΌλŠ” 방식
   public SpellChecker(Supplier<Dictionary> factorySupplier) // Supplier<T>κ°€ νŒ©ν„°λ¦¬λ₯Ό ν‘œν˜„ν•œ μ™„λ²½ν•œ 예
   {
      this.dictionary = factorySupplier.get();
   }
   
   
   public boolean isValid(String word)
   {
      return dictionary.contains(word);
   }
   
   public List<String> suggestions(String typo)
   {
      return dictionary.closeWordsTo(typo);
   }
}

Supplier<T>λ₯Ό μž…λ ₯으둜 λ°›λŠ” λ©”μ„œλ“œλŠ” 일반적으둜 ν•œμ •μ  μ™€μΌλ“œ μΉ΄λ“œ νƒ€μž…μ„ μ‚¬μš©ν•΄ νŒ©ν„°λ¦¬μ˜ νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό μ œν•œν•΄μ•Ό ν•œλ‹€. 

 

public class SpellChecker
{
   private final Dictionary dictionary;
   
   // μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ ν•„μš”ν•œ μžμ›μ„ λ„˜κ²¨μ£ΌλŠ” 방식
   public SpellChecker(Supplier<? extends Dictionary> factorySupplier) // Supplier<T>κ°€ νŒ©ν„°λ¦¬λ₯Ό ν‘œν˜„ν•œ μ™„λ²½ν•œ 예
   {
      this.dictionary = factorySupplier.get();
   }
   
   
   public boolean isValid(String word)
   {
      return dictionary.contains(word);
   }
   
   public List<String> suggestions(String typo)
   {
      return dictionary.closeWordsTo(typo);
   }
}

-> < ? extends Dictionary> λ₯Ό ν†΅ν•΄μ„œ ν΄λΌμ΄μ–ΈνŠΈλŠ” μžμ‹ μ΄ λͺ…μ‹œν•œ νƒ€μž…μ˜ ν•˜μœ„ νƒ€μž…μ΄λΌλ©΄ 무엇이든 생성할 수 μžˆλŠ” νŒ©ν„°λ¦¬λ₯Ό λ„˜κΈΈ μˆ˜μžˆλ‹€. 

 

 

πŸ‘©‍πŸ’»

μ‚¬μš©ν•˜λŠ” μžμ›μ— 따라 λ™μž‘μ΄ λ‹¬λΌμ§€λŠ” ν΄λž˜μŠ€λŠ” 정적 μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€λ‚˜ 싱글톀 방식을 μ‚¬μš©ν•˜λŠ” 것은 쒋지 μ•Šμ€ 방법이닀. 

이 λŒ€μ‹  ν•„μš”ν•œ μžμ›μ„ (ν˜Ήμ€ 이 μžμ›μ„ μƒμ„±ν•΄μ£ΌλŠ” νŒ©ν„°λ¦¬λ₯Ό) μƒμ„±μžμ— λ„˜κ²¨μ£ΌλŠ” 의쑴 객체 μ£Όμž…μ„ μ‚¬μš©ν•˜λŠ” 것을 ꢌμž₯ν•œλ‹€. 

의쑴 객체 μ£Όμž…μ„ μ‚¬μš©ν•˜λ©΄ 클래슀의 μœ μ—°μ„±, μž¬μ‚¬μš©μ„±, ν…ŒμŠ€νŠΈ μš©μ΄μ„±μ„ κ°œμ„ ν•  수 μžˆλ‹€. 

 

근데 μ˜μ‘΄μ„±μ΄ λ§Œμ•½ μˆ˜μ²œκ°œκ°€ λ˜λŠ” 큰 ν”„λ‘œμ νŠΈλ‹€ ν•˜λ©΄ 이 의쑴 객체 μ£Όμž…μ΄ μ½”λ“œλ₯Ό μ§€μ €λΆ„ν•˜κ²Œ λ§Œλ“€κΈ°λ„ ν•œλ‹€. 

(μ˜μ‘΄μ„±μ΄ 수천개만 의쑴 μ£Όμž… μ½”λ“œλ§Œ μˆ˜μ²œμ€„ 될듯..)

-> 이에 λŒ€ν•΄μ„œλŠ” λŒ€κ±° Dagger, 주슀 Guice, μŠ€ν”„λ§ Spring κ³Ό 같은 의쑴 객체 μ£Όμž… ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜λ©΄ ν•΄μ†Œν•  수 μžˆλ‹€. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90