Skip to content

Commit

Permalink
Merge pull request #266 from SSONG22/item5-songi
Browse files Browse the repository at this point in the history
[#5][2κΈ°] μžμ›μ„ 직접 λͺ…μ‹œν•˜μ§€ 말고 의쑴 객체 μ£Όμž…μ„ μ‚¬μš©ν•˜λΌ
  • Loading branch information
ksy90101 authored May 16, 2021
2 parents 6a9a6f1 + 1a4f7a4 commit 78b76c4
Showing 1 changed file with 262 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# μ•„μ΄ν…œ 5 μžμ›μ„ 직접 λͺ…μ‹œν•˜μ§€ 말고 의쑴 객체 μ£Όμž…μ„ μ‚¬μš©ν•˜λΌ

---

> ν΄λž˜μŠ€κ°€ λ‚΄λΆ€μ μœΌλ‘œ ν•˜λ‚˜ μ΄μƒμ˜ **μžμ›**에 μ˜μ‘΄ν•˜κ³ ,
κ·Έ μžμ›μ΄ 클래슀 λ™μž‘μ— 영ν–₯을 μ€€λ‹€λ©΄
μ‹±κΈ€ν„΄(Singleton) κ³Ό, 정적 μœ ν‹Έλ¦¬ν‹°(static util class)λŠ” μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것이 μ’‹λ‹€.

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

- 정적 μœ ν‹Έλ¦¬ν‹°λ₯Ό 잘λͺ» μ‚¬μš©ν•œ 예 - μœ μ—°ν•˜μ§€ μ•Šκ³  ν…ŒμŠ€νŠΈν•˜κΈ° μ–΄λ ΅λ‹€

```java
// 정적 μœ ν‹Έλ¦¬ν‹°λ₯Ό 잘λͺ» μ‚¬μš©ν•œ 예 - μœ μ—°ν•˜μ§€ μ•Šκ³  ν…ŒμŠ€νŠΈν•˜κΈ° μ–΄λ ΅λ‹€
public class SpellChecker{
private static final Lexicon dictionary = ...; // 사전에 의쑴
private SpellChecker() {} // 객체 생성 방지
public static boolean isValid(String word){...}
public static List<String> suggestions(String typo){...}
}
```

- 싱글턴을 잘λͺ» μ‚¬μš©ν•œ 예 - μœ μ—°ν•˜μ§€ μ•Šκ³  ν…ŒμŠ€νŠΈν•˜κΈ° μ–΄λ ΅λ‹€

```java
// 싱글턴을 잘λͺ» μ‚¬μš©ν•œ 예 - μœ μ—°ν•˜μ§€ μ•Šκ³  ν…ŒμŠ€νŠΈν•˜κΈ° μ–΄λ ΅λ‹€
public class SpellChecker{
private static final Lexicon dictionary = ...; // 사전에 의쑴
private SpellChecker(...) {}
public static SpellChecker INSTANCE = new SpellChecker(...);

public static boolean isValid(String word){...}
public static List<String> suggestions(String typo){...}

}
```

- SpellChecker ν΄λž˜μŠ€λŠ” dictionary(μžμ›)에 μ˜μ‘΄ν•˜κ³  μžˆλ‹€
- 그런데, 언어별 사전, 특수 μ–΄νœ˜μš© 사전이 ν•„μš”ν•˜κ²Œ 되면 클래슀 λ‚΄λΆ€ λ©”μ„œλ“œ λ™μž‘μ΄ 달라져야 ν•œλ‹€.
- 정적 μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€λ‚˜ μ‹±κΈ€ν„΄ 방식은 μ ν•©ν•˜μ§€ μ•Šλ‹€.

> μ™œλƒν•˜λ©΄, μœ μ—°ν•˜μ§€ μ•Šκ³ , ν…ŒμŠ€νŠΈ ν•˜κΈ° μ–΄λ ΅κΈ° λ•Œλ¬Έμ΄λ‹€.

- SpellCheckerκ°€ μ—¬λŸ¬ 사전을 μ‚¬μš©ν•  수 μžˆλ„λ‘ λ§Œλ“€κΈ° μœ„ν•΄ dictionary ν•„λ“œμ—μ„œ final ν•œμ •μžλ₯Ό μ œκ±°ν•˜κ³  λ‹€λ₯Έ μ‚¬μ „μœΌλ‘œ κ΅μ²΄ν•˜λŠ” λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•  μˆ˜λŠ” μžˆλ‹€.
- κ·ΈλŸ¬λ‚˜ 이 방법은 μ–΄μƒ‰ν•˜λ©°, 였λ₯˜λ₯Ό λ‚΄κΈ° 쉽닀. λ˜ν•œ λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œλŠ” μ“Έ 수 μ—†λ‹€.

> ν΄λž˜μŠ€κ°€ μ—¬λŸ¬ μžμ› μΈμŠ€ν„΄μŠ€λ₯Ό μ§€μ›ν•΄μ•Όν•˜κ³ , ν΄λΌμ΄μ–ΈνŠΈκ°€ μ›ν•˜λŠ” μžμ›μ„ μ‚¬μš©ν•˜κ²Œ ν•˜λŠ” 방법을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ μƒμ„±μžμ— ν•„μš”ν•œ μžμ›μ„ λ„˜κ²¨μ£Όμž.

- **의쑴 객체 μ£Όμž… 방식** μ΄λΌκ³ ν•œλ‹€.

```java
// 의쑴 객체 μ£Όμž…μ€ μœ μ—°μ„±κ³Ό ν…ŒμŠ€νŠΈ μš©μ΄μ„±μ„ λ†’μ—¬μ€€λ‹€
public class SpellChecker{
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary){
this.dictionay = Objects.requiredNonNull(dictionay);
}
public boolean isValid(String word){...}
public List<String> suggestions(String typo){...}
}
```

- 클래슀의 μœ μ—°μ„±, μž¬μ‚¬μš©μ„±, ν…ŒμŠ€νŠΈ μš©μ΄μ„±μ„ κ°œμ„  ν•΄μ€€λ‹€.
- λΆˆλ³€μ„ 보μž₯ν•΄ ν•΄λ‹Ή μžμ›μ„ μ‚¬μš©ν•˜λ €λŠ” μ—¬λŸ¬ ν΄λΌμ΄μ–ΈνŠΈκ°€ 의쑴 객체듀을 μ•ˆμ‹¬ν•˜κ³  κ³΅μœ ν•  수 μžˆλ‹€.
- μƒμ„±μž, 정적 νŒ©ν„°λ¦¬, λΉŒλ” μ•„μ΄ν…œμ— μ‘μš©ν•  수 μžˆλ‹€.

```java
public class λ°°λ‹¬μ„œλΉ„μŠ€{
private final 배달 μΉ˜ν‚¨λ°°λ‹¬;
// 정적 μœ ν‹Έλ¦¬ν‹°
private λ°°λ‹¬μ„œλΉ„μŠ€(){}; //객체 생성 방지
public static void λ°°λ‹¬μ‹œμž‘(){}
}
public class λ°°λ‹¬μ„œλΉ„μŠ€{
private final 배달 μΉ˜ν‚¨λ°°λ‹¬;
private λ°°λ‹¬μ„œλΉ„μŠ€(..){..};
public static λ°°λ‹¬μ„œλΉ„μŠ€ Instance = new λ°°λ‹¬μŒμ‹μ„œλΉ„μŠ€(..); // μ‹±κΈ€ν„΄ νŒ¨ν„΄
public static void λ°°λ‹¬μ‹œμž‘(){}
}
// μΉ˜ν‚¨λ°°λ‹¬λ§Œ κ°€λŠ₯ν•˜λ‹€ ...
```

```java
public class λ°°λ‹¬μ„œλΉ„μŠ€{
private final 배달 μŒμ‹λ°°λ‹¬;
public λ°°λ‹¬μ„œλΉ„μŠ€(배달 μŒμ‹μ΄λ¦„){
this.μŒμ‹λ°°λ‹¬ = μŒμ‹μ΄λ¦„;
}
public static void λ°°λ‹¬μ‹œμž‘(){}
}
// μ–΄λ–€ μŒμ‹λ„ 배달할 수 μžˆλŠ” μ„œλΉ„μŠ€κ°€ λ˜μ—ˆλ‹€ !
```

> 의쑴 객체 μ£Όμž… μ‘μš© : μƒμ„±μžμ— μžμ› νŒ©ν„°λ¦¬(Factory) λ₯Ό λ„˜κ²¨ μ£ΌλŠ” 방식
- νŒ©ν„°λ¦¬(Factory) : ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ νŠΉμ • νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜λ³΅ν•΄μ„œ λ§Œλ“€μ–΄μ£ΌλŠ” 객체
- νŒ©ν„°λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄ (Factory Method pattern) : μƒμ„±μžμ— μžμ› νŒ©ν„°λ¦¬λ₯Ό λ„˜κ²¨μ£ΌλŠ” 방식

<details>
<summary>νŒ©ν„°λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄</summary>
<div markdown="1">

- νŒ©ν„°λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄
- 객체 생성을 μΊ‘μŠν™” ν•˜λŠ” νŒ¨ν„΄μ΄λ‹€
- 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜μ§€λ§Œ, μ–΄λ–€ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할지에 λŒ€ν•œ 결정은 μ„œλΈŒ ν΄λž˜μŠ€κ°€ λ‚΄λ¦°λ‹€.
- Creator의 μ„œλΈŒ ν΄λž˜μŠ€μ— νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ •μ˜ ν•˜λ©°, νŒ©ν„°λ¦¬ λ©”μ„œλ“œ 호좜둜 ConcreteProduct μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜κ²Œ ν•œλ‹€.
- μ˜ˆμ œμ½”λ“œ

```java
// Product μ—­ν• 
public interface Shopping {
// 쇼핑을 ν•  λ•Œ 곡톡 κ³Όμ •
void find();
void cart();
void order();
}

// Creator (Factory)
public abstract class Shop {
public Shopping shopping(String category){
Shopping shopping = selectCategory(category);
shopping.find();
shopping.cart();
shopping.order();
return shopping;
}

// factory method
abstract Shopping selectCategory(String category);
}
```

```java
public class MarketOne extends Shop {
@Override
Shopping selectCategory(String category) {
System.out.println("THIS IS MARKET ONE.");
if (category.equals("FOOD")) return new MarketOneFoodCategory();
if (category.equals("HEALTH")) return new MarketOneHealthCategory();
return null;
}
}
public class MarketOneFoodCategory implements Shopping {
@Override
public void find() {
System.out.println("market-one: food 검색 ");
}

@Override
public void cart() {
System.out.println("market-one: food λ‹΄κΈ° ");
}

@Override
public void order() {
System.out.println("market-one: food μ£Όλ¬Έ ");
}
}
```
</div>
</details>

- μžλ°” 8의 Supplier<T> μΈν„°νŽ˜μ΄μŠ€κ°€ λ¦¬μ†ŒμŠ€μ˜ μƒμ„±μžμ— μ „λ‹¬ν•˜λŠ” νŒ©ν„°λ¦¬λ‘œ 쓰기에 μ ν•©ν•˜λ‹€.

```java
Mosaic create(Supplier<? extends Tile> tileFactory){..}
```

---

- μ˜μ‘΄μ„±μ΄ μˆ˜μ²œκ°œκ°€ λ˜λŠ” 큰 ν”„λ‘œμ νŠΈμ—μ„œλŠ” 의쑴 객체 μ£Όμž…μ΄ μ½”λ“œλ₯Ό μ–΄μ§€λŸ½κ²Œ λ§Œλ“€κΈ°λ„ ν•œλ‹€.
- λŒ€κ±°, 주슀, μŠ€ν”„λ§ 같은 의쑴 객체 μ£Όμž… ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜λ©΄ 이런 μ–΄μ§ˆλŸ¬μ§μ„ ν•΄μ†Œν•  수 μžˆλ‹€.

<details>
<summary>μŠ€ν”„λ§ μ˜μ‘΄μ„± μ£Όμž…</summary>
<div markdown="1">

- μŠ€ν”„λ§ μ˜μ‘΄μ„± μ£Όμž…
- μŠ€ν”„λ§ 핡심 κΈ°λŠ₯ DI (Dependency Injection)

**μ™ΈλΆ€**(IOCμ»¨ν…Œμ΄λ„ˆ) μ—μ„œ 객체λ₯Ό μƒμ„±ν•œ ν›„ μ˜μ‘΄μ„±μ„ μ£Όμž…μ‹œν‚¨λ‹€

```java
@Service
public class ShopService{
public void findAllShop(){
ShopRepository shopRepository = new FoodShop();
shopRepository.findAll();
}
}
```

```java
@Service
public class ShopService{
private ShopRepository shopRepository;
public ShopService(ShopRepository shopRepository){
this.shopRepository = shopRepository;
}
public void findAllShop(){
shopRepository.findAll();
}
}

@Test
public class testFindAll(){
ShopRepository foodShop = new FoodShop();
ShopService shopService = new ShopService(foodShop);
shopService.findAll();
}
```

μ˜μ‘΄μ„± μ£Όμž…λ°©λ²•

1. μƒμ„±μž 이용

```java
@Service
public class ShopService{
private ShopRepository shopRepository;
public ShopService(ShopRepository shopRepository){
this.shopRepository = shopRepository;
}
}
```

2. Field λ³€μˆ˜ 이용

```java
@Service
public class ShopService{
@Autowired
private ShopRepository shopRepository;
}
```

3. setter 이용

```java
@Service
public class ShopService{
private ShopRepository shopRepository;
@Autowired
public ShopService(ShopRepository shopRepository){
this.shopRepository = shopRepository;
}
}
```


</div>
</details>

---


### 핡심 정리

- ν΄λž˜μŠ€κ°€ λ‚΄λΆ€μ μœΌλ‘œ ν•˜λ‚˜ μ΄μƒμ˜ μžμ›μ— μ˜μ‘΄ν•˜κ³ , κ·Έ μžμ›μ΄ 클래슀 λ™μž‘μ— 영ν–₯을 μ€€λ‹€λ©΄ μ‹±κΈ€ν„΄κ³Ό 정적 μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€λŠ” μ‚¬μš©ν•˜μ§€ 말자.
- 이 μžμ›λ“€μ„ ν΄λž˜μŠ€κ°€ 직접 λ§Œλ“€κ²Œ ν•΄μ„œλ„ μ•ˆλœλ‹€.
- ν•„μš”ν•œ μžμ›μ„ (ν˜Ήμ€ κ·Έ μžμ›μ„ λ§Œλ“€μ–΄μ£ΌλŠ” νŒ©ν„°λ¦¬λ₯Ό) μƒμ„±μžμ— (ν˜Ήμ€ 정적 νŒ©ν„°λ¦¬λ‚˜ λΉŒλ”μ—) λ„˜κ²¨μ£Όμž. 의쑴 객체 μ£Όμž…μ΄λΌ ν•˜λŠ” 이 기법은 클래슀의 μœ μ—°μ„±, μž¬μ‚¬μš©μ„±, ν…ŒμŠ€νŠΈ μš©μ΄μ„±μ„ κΈ°λ§‰νžˆκ²Œ κ°œμ„ ν•΄μ€€λ‹€.

0 comments on commit 78b76c4

Please sign in to comment.