Post

🦊 chap2. λ™μž‘ νŒŒλΌλ―Έν„°ν™” μ½”λ“œ μ „λ‹¬ν•˜κΈ°

λ³€ν™”ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ€ μ†Œν”„νŠΈμ›¨μ–΄ μ—”μ§€λ‹ˆμ–΄λ§μ—μ„œ ν”Όν•  수 μ—†λŠ” λ¬Έμ œμ΄λ‹€.

μ‹œμ‹œκ°κ° λ³€ν•˜λŠ” μ‚¬μš©μž μš”κ΅¬μ‚¬ν•­μ— μ–΄λ–»κ²Œ λŒ€μ‘ν•΄μ•Ό ν• κΉŒ?

2.1 λ³€ν™”ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ— λŒ€μ‘ν•˜κΈ°

2.1.1 첫 번째 μ‹œλ„ : 녹색 사과 필터링

사과 색을 μ •μ˜ν•˜λŠ” λ‹€μŒ enum 이 μ‘΄μž¬ν•œλ‹€κ³  ν•˜μž

1
enum Color { RED, GREEN }
1
2
3
4
5
6
7
8
9
public static List<Apple> filterGreenApples(List<Apple> inventory) {
	List<Apple> result = new ArrayList<>();
	for (Apple apple: inventory) {
		if (GREEN.equals(apple.getColor()) {
			result.add(apple);
		}
	}
	return result;
}

κ°‘μžκΈ° 농뢀가 λ³€μ‹¬ν•˜μ—¬ μ΄ˆλ‘μƒ‰μ΄ μ•„λ‹Œ 빨간색 사과λ₯Ό 필터링 ν•˜κ³  싢어진닀면 μ–΄λ–»κ²Œ 고쳐야 ν• κΉŒ?

크게 κ³ λ―Όν•˜μ§€ μ•Šμ€ μ‚¬λžŒμ΄λΌλ©΄ λ©”μ„œλ“œλ₯Ό 볡사해 filterRedApples λΌλŠ” μƒˆλ‘œμš΄ λ©”μ„œλ“œλ₯Ό λ§Œλ“€κ³ , if 문의 쑰건을 λ°”κΏ€ 것이닀

ν•˜μ§€λ§Œ λ‚˜μ€‘μ— 더 λ‹€μ–‘ν•œ μƒ‰μƒμ—λŠ” λŒ€μ‘ν•  수 μ—†λ‹€.

이런 μƒν™©μ—μ„œλŠ” 거의 λΉ„μŠ·ν•œ μ½”λ“œκ°€ 반볡 μ‘΄μž¬ν•œλ‹€λ©΄ κ·Έ μ½”λ“œλ₯Ό μΆ”μƒν™”ν•œλ‹€. λΌλŠ” 쒋은 κ·œμΉ™μ΄ μžˆλ‹€.

2.1.2 두 번째 μ‹œλ„ : 색을 νŒŒλΌλ―Έν„°ν™”

색을 νŒŒλΌλ―Έν„°ν™” ν•  수 μžˆλ„λ‘ λ©”μ„œλ“œμ— νŒŒλΌλ―Έν„°λ₯Ό μΆ”κ°€ν•˜λ©΄ λ³€ν™”ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ— μ’€ 더 μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•  수 μžˆλ‹€.

1
2
3
4
5
6
7
8
9
public static List<Apple> filterApplesByColor(List<Apple> inventory, Color color) {
	List<Apple> result = new ArrayList<>();
	for (Apple apple: inventory) {
		if (apple.getColor().equals(color) {
			result.add(apple);
		}
	}
	return result;
}

그런데 농뢀가 또 λ³€μ‹¬ν•˜μ—¬ λ¬΄κ²Œκ°€ 150g 이상인 사과λ₯Ό κ΅¬λ³„ν•˜κ³  μ‹Άλ‹€κ³  ν•˜λ©΄?

무게 정보 νŒŒλΌλ―Έν„°λ„ μΆ”κ°€ν–ˆλ‹€.

1
2
3
4
5
6
7
8
9
public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight) {
	List<Apple> result = new ArrayList<>();
	for (Apple apple: inventory) {
		if (apple.getWeight() > weight {
			result.add(apple);
		}
	}
	return result;
}

μ΄λ ‡κ²Œ κ΅¬ν˜„ μ½”λ“œκ°€ μ€‘λ³΅λœλ‹€λ©΄ μ†Œν”„νŠΈμ›¨μ–΄ κ³΅ν•™μ˜ DRY(don’t repeat yourself) 원칙을 μ–΄κΈ°λŠ” 것이닀.

2.1.3 μ„Έ 번째 μ‹œλ„ : κ°€λŠ₯ν•œ λͺ¨λ“  μ†μ„±μœΌλ‘œ 필터링

μƒ‰μ΄λ‚˜ 무게 쀑 μ–΄λ–€ κ²ƒμœΌλ‘œ 필터링할지 κ°€λ¦¬ν‚€λŠ” ν”Œλž˜κ·Έλ₯Ό μ •ν•  μˆ˜λ„ μžˆλ‹€.

(ν•˜μ§€λ§Œ μ‹€μ „μ—μ„œλŠ” μ ˆλŒ€ 이 방법을 μ‚¬μš©ν•΄μ„œλŠ” μ•ˆλœλ‹€)

1
2
3
4
5
6
7
8
9
10
public static List<Apple> filterApples(List<Apple> inventory, Color color, int weight, boolean flag) {
	List<Apple> result = new ArrayList<>();
	for (Apple apple: inventory) {
		if ((flag && apple.getColor().equals(color)) ||
				(!flag && apple.getWeight() > weight) {
			result.add(apple);
		}
	}
	return result;
}

ν˜•νŽΈμ—†λŠ” μ½”λ“œμ΄λ‹€. true false κ°€ λŒ€μ²΄ 무엇을 μ˜λ―Έν•˜λŠ” 것인지 μ•Œ 수 μ—†λ‹€.

λ³€ν™”ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ— μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•  μˆ˜λ„ μ—†λ‹€.

2.2 λ™μž‘ νŒŒλΌλ―Έν„°ν™”

μ°Έ λ˜λŠ” 거짓을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λ₯Ό Predicate 라고 ν•œλ‹€.

선택 쑰건을 κ²°μ •ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•œλ‹€.

1
2
3
public interface ApplePredicate {
	boolean test (Apple apple);
}

λ‹€μ–‘ν•œ 선택 쑰건을 λŒ€ν‘œν•˜λŠ” μ—¬λŸ¬ λ²„μ „μ˜ ApplePredicate λ₯Ό μ •μ˜ν•  수 μžˆλ‹€.

1
2
3
4
5
public class AppleHeavyWeightPredicate implements ApplePredicate {
	public boolean test(Apple apple) {
		return apple.getWeight() > 150;
	}
}
1
2
3
4
5
public class AppleGreenColorPredicate implements ApplePredicate {
	public boolean test(Apple apple) {
		return GREEN.equals(apple.getColor());
	}
}

μœ„ 쑰건에 따라 filter λ©”μ„œλ“œκ°€ λ‹€λ₯΄κ²Œ λ™μž‘ν•  것이라고 μ˜ˆμƒν•  수 μžˆλ‹€.

이λ₯Ό μ „λž΅ λ””μžμΈ νŒ¨ν„΄(Strategy design pattern) 이라고 ν•œλ‹€.

μ „λž΅ λ””μžμΈ νŒ¨ν„΄μ€ μ „λž΅μ΄λΌ λΆˆλ¦¬λŠ” 각 μ•Œκ³ λ¦¬μ¦˜μ„ μΊ‘μŠν™” ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜ νŒ¨λ°€λ¦¬λ₯Ό μ •μ˜ν•΄ λ‘” λ‹€μŒμ—

λŸ°νƒ€μž„μ— μ•Œκ³ λ¦¬μ¦˜μ„ μ„ νƒν•˜λŠ” 기법이닀.

μ—¬κΈ°μ—μ„œλŠ” ApplePredicate κ°€ μ•Œκ³ λ¦¬μ¦˜ νŒ¨λ°€λ¦¬μ΄κ³ 

AppleHeavyWeightPredicate 와 AppleGreenColorPredicate κ°€ μ „λž΅μ΄λ‹€.

λ™μž‘ νŒŒλΌλ―Έν„°ν™”, 즉 λ©”μ„œλ“œκ°€ λ‹€μ–‘ν•œ λ™μž‘ λ˜λŠ” μ „λž΅μ„ λ°›μ•„μ„œ λ‚΄λΆ€μ μœΌλ‘œ λ‹€μ–‘ν•œ λ™μž‘μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.

2.2.1 λ„€ 번째 μ‹œλ„ : 좔상적 쑰건으둜 필터링

1
2
3
4
5
6
7
8
9
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
	List<Apple> result = new ArrayList<>();
	for (Apple apple: inventory) {
		if (p.test(apple) {
			result.add(apple);
		}
	}
	return result;
}

μš°λ¦¬λŠ” filterApples λ©”μ„œλ“œμ˜ λ™μž‘μ„ νŒŒλΌλ―Έν„°ν™” ν–ˆλ‹€.

μ΄λŠ” μ½”λ“œλ₯Ό λ©”μ„œλ“œμ— μ „λ‹¬ν•œ κ²ƒμ΄λ‚˜ 닀름없닀.

ν•˜μ§€λ§Œ μ—¬λŸ¬ 클래슀λ₯Ό κ΅¬ν˜„ν•΄μ„œ μΈμŠ€ν„΄μŠ€ν™”ν•˜λŠ” 과정이 μ‘°κΈˆμ€ κ±°μΆ”μž₯μŠ€λŸ½λ‹€.

이 뢀뢄을 μ–΄λ–»κ²Œ κ°œμ„ ν•  수 μžˆμ„κΉŒ

2.3 λ³΅μž‘ν•œ κ³Όμ • κ°„μ†Œν™”

ν˜„μž¬λŠ” filterApples λ©”μ„œλ“œλ‘œ μƒˆλ‘œμš΄ λ™μž‘μ„ μ •μ˜ν•˜λ €λ©΄ ApplePredicate μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” μ—¬λŸ¬ 클래슀λ₯Ό μ •μ˜ν•œ λ‹€μŒμ— μΈμŠ€ν„΄μŠ€ν™”ν•΄μ•Ό ν•œλ‹€. μ΄λŠ” μƒλ‹Ήνžˆ 번거둭고 μ‹œκ°„ 낭비이닀.

클래슀의 μ„ μ–Έκ³Ό μΈμŠ€ν„΄μŠ€ν™”λ₯Ό λ™μ‹œμ— μˆ˜ν–‰ν•  수 μžˆλ„λ‘ 읡λͺ… ν΄λž˜μŠ€λΌλŠ” 기법을 μ‚¬μš©ν•΄λ³΄μž.

2.3.1 읡λͺ… 클래슀

읡λͺ… 클래슀λ₯Ό μ΄μš©ν•˜λ©΄ 클래슀 μ„ μ–Έκ³Ό μΈμŠ€ν„΄μŠ€ν™”λ₯Ό λ™μ‹œμ— ν•  수 μžˆλ‹€.

2.3.2 λ‹€μ„― 번째 μ‹œλ„ : 읡λͺ… 클래슀 μ‚¬μš©

1
2
3
4
5
List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
	public boolean test(Apple apple) {
		return RED.equals(apple.getColor());
	}
}

읡λͺ… ν΄λž˜μŠ€λ‘œλ„ 아직 λΆ€μ‘±ν•œ 점이 μžˆλ‹€. 읡λͺ… ν΄λž˜μŠ€λŠ” μ—¬μ „νžˆ λ§Žμ€ 곡간을 μ°¨μ§€ν•œλ‹€.

μ½”λ“œμ˜ μž₯황함은 λ‚˜μœ νŠΉμ„±μ΄λ‹€. κ΅¬ν˜„ν•˜κ³  μœ μ§€λ³΄μˆ˜ν•˜λŠ” 데 μ‹œκ°„μ΄ 였래 걸리고 μ½λŠ” 즐거움을 λΉΌμ•—λŠ”λ‹€.

2.3.3 μ—¬μ„― 번째 μ‹œλ„ : λžŒλ‹€ ν‘œν˜„μ‹ μ‚¬μš©

μžλ°” 8의 λžŒλ‹€ ν‘œν˜„μ‹μ„ μ΄μš©ν•΄μ„œ κ°„λ‹¨ν•˜κ²Œ μž¬κ΅¬ν˜„ν•  수 μžˆλ‹€.

1
2
List<Apple> redApples = filterApples(inventory, 
			(Apple apple) -> RED.equals(apple.getColor()));

κ°„κ²°ν•΄μ§€λ©΄μ„œ 문제λ₯Ό 더 잘 μ„€λͺ…ν•˜λŠ” μ½”λ“œκ°€ λ˜μ—ˆλ‹€.

2.3.4 일곱 번째 μ‹œλ„ : 리슀트 ν˜•μ‹μœΌλ‘œ 좔상화

1
2
3
4
5
6
7
8
9
10
11
12
public interface Predicate<T> {
	boolean test(T t);
}

public static <T> List<T> filter(List<T> list, Predicate<T> p) {
	List<T> result = new ArrayList<>();
	for(T e: list) {
		if(p.test(e)) {
			result.add(e);
		}
	}
}

이제 λ°”λ‚˜λ‚˜, μ˜€λ Œμ§€, μ •μˆ˜, λ¬Έμžμ—΄ λ“±μ˜ λ¦¬μŠ€νŠΈμ— ν•„ν„° λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

1
2
3
4
5
List<Apple> redApples = 
	filter(inventory, (Apple apple) -> RED.equals(apple.getColor()));

List<Integer> evenNumbers =
	filter(numbers, (Integer i) -> i % 2 == 0);

2.4 μ‹€μ „ 예제

2.4.1 Comparator둜 μ •λ ¬ν•˜κΈ°

μ»¬λ ‰μ…˜ 정렬은 λ°˜λ³΅λ˜λŠ” ν”„λ‘œκ·Έλž˜λ° μž‘μ—…μ΄λ‹€.

μžλ°” 8의 Listμ—λŠ” sort λ©”μ„œλ“œκ°€ ν¬ν•¨λ˜μ–΄ μžˆλ‹€.

λ‹€μŒκ³Ό 같은 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ°–λŠ” java.util.Comparator 객체λ₯Ό μ΄μš©ν•˜μ—¬

sort 의 λ™μž‘μ„ νŒŒλΌλ―Έν„°ν™”ν•  수 μžˆλ‹€.

1
2
3
public interface Comparator<T> {
	int compare(T o1, T o2);
}

이λ₯Ό μ΄μš©ν•΄μ„œ λ¬΄κ²Œκ°€ 적은 μˆœμ„œλ‘œ 사과λ₯Ό μ •λ ¬ν•  수 μžˆλ‹€.

1
2
3
4
5
inventory.sort(new Comparator<Apple>() {
	public int compare(Apple a1, Apple a2) {
		return a1.getWeight().compareTo(a2.getWeight());
	}
}

λžŒλ‹€λ₯Ό μ‚¬μš©ν•΄μ„œ κ°„λ‹¨ν•˜κ²Œ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

1
2
inventory.sort(
	(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

2.4.2 Runnable둜 μ½”λ“œ 블둝 μ‹€ν–‰ν•˜κΈ°

μžλ°” μŠ€λ ˆλ“œλ₯Ό μ΄μš©ν•˜λ©΄ 병렬 μ½”λ“œ 블둝 싀행이 κ°€λŠ₯ν•˜λ‹€.

μžλ°” 8κΉŒμ§€λŠ” Thread μƒμ„±μžμ— κ°μ²΄λ§Œμ„ 전달할 수 μžˆμ—ˆκΈ° λ•Œλ¬Έμ— 보톡 κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜μ§€ μ•ŠλŠ” void run λ©”μ†Œλ“œλ₯Ό ν¬ν•¨ν•˜λŠ” 읡λͺ… ν΄λž˜μŠ€κ°€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λ„λ‘ ν•˜λŠ” 것이 μΌλ°˜μ μ΄μ—ˆλ‹€.

μžλ°”μ—μ„œλŠ” Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•˜μ—¬ μ‹€ν–‰ν•  μ½”λ“œ 블둝을 지정할 수 μžˆλ‹€.

1
2
3
public interface Runnable {
	void run();
}

Runnable을 μ΄μš©ν•΄μ„œ λ‹€μ–‘ν•œ λ™μž‘μ„ μŠ€λ ˆλ“œλ‘œ μ‹€ν–‰ν•  수 μžˆλ‹€.

1
2
3
4
5
Thread t = new Thread(new Runnable() {
	public void run() {
		System.out.println("Hello world");
	}
});

μžλ°” 8λΆ€ν„° μ§€μ›ν•˜λŠ” λžŒλ‹€ ν‘œν˜„μ‹μ„ μ΄μš©ν•˜λ©΄ λ‹€μŒμ²˜λŸΌ μŠ€λ ˆλ“œ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

1
Thread t = new Thread(() -> System.out.println("Hello world"));

2.4.3 Callable을 결과둜 λ°˜ν™˜ν•˜κΈ°

μžλ°” 5λΆ€ν„° μ§€μ›ν•˜λŠ” ExecutorService μΈν„°νŽ˜μ΄μŠ€λŠ” νƒœμŠ€ν¬ 제좜과 μ‹€ν–‰ κ³Όμ •μ˜ 연관성을 λŠμ–΄μ€€λ‹€. 이λ₯Ό μ΄μš©ν•˜λ©΄ νƒœμŠ€ν¬λ₯Ό μŠ€λ ˆλ“œ ν’€λ‘œ 보내고 κ²°κ³Όλ₯Ό Future 둜 μ €μž₯ν•  수 μžˆλ‹€.

1
2
3
public interface Callable<V> {
	V call();
}

μ‹€ν–‰ μ„œλΉ„μŠ€μ— νƒœμŠ€ν¬λ₯Ό μ œμΆœν•΄μ„œ μœ„ μ½”λ“œλ₯Ό ν™œμš©ν•  수 μžˆλ‹€.

1
2
3
4
5
6
7
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> threadName = executorService.submit(new Callable<String>() {
	@Override
	public String call() throws Exception {
		return Thread.currentThread().getName();
	}
});

λžŒλ‹€λ₯Ό μ΄μš©ν•˜λ©΄

1
2
Future<String> threadName = executorService.submit(
	() -> Thread.currentThread().getName());

2.4.4 GUI 이벀트 μ²˜λ¦¬ν•˜κΈ°

GUI ν”„λ‘œκ·Έλž˜λ°μ€ 마우슀 ν΄λ¦­μ΄λ‚˜ λ¬Έμžμ—΄ μœ„λ‘œ μ΄λ™ν•˜λŠ” λ“±μ˜ μ΄λ²€νŠΈμ— λŒ€μ‘ν•˜λŠ” λ™μž‘μ„ μˆ˜ν–‰ν•˜λŠ” μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€.

μžλ°”FXμ—μ„œλŠ” setOnAction λ©”μ„œλ“œμ— EventHandler λ₯Ό μ „λ‹¬ν•¨μœΌλ‘œμ¨ μ΄λ²€νŠΈμ— μ–΄λ–»κ²Œ λ°˜μ‘ν• μ§€ μ„€μ •ν•  수 μžˆλ‹€.

1
2
3
4
5
6
Buttin button = new Button("Send");
button.setOnAction(new EventHandler<ActionEvent>() {
	public void handle(ActionEvent event) {
		label.setText("Sent!!");
	}
});

λžŒλ‹€λ₯Ό μ‚¬μš©ν•˜λ©΄

1
button.setOnAction((ActionEvent event) -> label.setText("Sent!!"));
This post is licensed under CC BY 4.0 by the author.