Post

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

λ™μž‘ νŒŒλΌλ―Έν„°ν™”(behavior parameterization)

아직은 μ–΄λ–»κ²Œ μ‹€ν–‰ν•  것인지 κ²°μ •ν•˜μ§€ μ•Šμ€ μ½”λ“œ 블둝

이 μ½”λ“œ λΈ”λ‘μ˜ 싀행은 λ‚˜μ€‘μœΌλ‘œ 미뀄지고, 결과적으둜 μ½”λ“œ 블둝에 따라 λ©”μ„œλ“œμ˜ λ™μž‘μ΄ νŒŒλΌλ―Έν„°ν™”λ¨

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

사과 농μž₯의 재고 νŒŒμ•…μ„ μœ„ν•œ 리슀트 필터링 κΈ°λŠ₯을 μ˜ˆμ‹œλ‘œ ν•œλ‹€.

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

사과 색을 μ •μ˜ν•˜λŠ” Color num이 μ‘΄μž¬ν•œλ‹€.

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
10
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;
}

λ‹€μŒμ²˜λŸΌ κ΅¬ν˜„ν•œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œλ‹€.

1
2
List<Apple> greenApples = filterApplesByColor(inventory, GREEN);
List<Apple> redApples = filterApplesByColor(inventory, RED);

κ°‘μžκΈ° μ—¬κΈ°μ„œ 농뢀가 β€˜μƒ‰ 이외에도 사과λ₯Ό 무게둜 ꡬ뢄할 수 μžˆλ‹€λ©΄ μ’‹κ² λ‹€β€™λΌλŠ” μš”κ΅¬λ₯Ό ν•œλ‹€.

λ‹€μ–‘ν•œ λ¬΄κ²Œμ— λŒ€μ‘ν•  수 μžˆλ„λ‘ 무게 정보 νŒŒλΌλ―Έν„°λ„ μΆ”κ°€ν•œλ‹€.

1
2
3
4
5
6
7
8
9
10
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) 원칙을 μ–΄κΈ°λŠ” 것이닀.

색과 무게λ₯Ό filterλΌλŠ” λ©”μ„œλ“œλ‘œ ν•©μΉ˜λŠ” 방법이 μžˆμ§€λ§Œ μ΄λŠ” μ–΄λ–€ κΈ°μ€€μœΌλ‘œ 사과λ₯Ό 필터링할 지 κ΅¬λΆ„ν•˜λŠ” 또 λ‹€λ₯Έ λ°©λ²•μœΌλ‘œ ν”Œλž˜κ·Έλ₯Ό μΆ”κ°€ν•΄μ•Όν•œλ‹€. ν•˜μ§€λ§Œ μ‹€μ „μ—μ„œλŠ” μ ˆλŒ€ 이 방법을 μ‚¬μš©ν•˜μ§€ 말아야 ν•œλ‹€.

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

λ‹€μŒμ€ λͺ¨λ“  속성을 λ©”μ„œλ“œ νŒŒλΌλ―Έν„°λ‘œ μΆ”κ°€ν•œ μ½”λ“œμ΄λ‹€.(ν•˜μ§€ 말아야 ν•  짓)

1
2
3
4
5
6
7
8
9
10
11
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;
}

μ‹€ν–‰ μ½”λ“œ

1
2
List<Apple> greenApples = filterApples(inventory, GREEN, 0, true);
List<Apple> heavyApples = filterApples(inventroy, null, 150, false);

μœ„ μ½”λ“œλ₯Ό 봀을 λ•Œ true와 falseκ°€ 무엇을 μ˜λ―Έν•˜λŠ”μ§€ νŒŒμ•…ν•˜κΈ° μ–΄λ ΅κ³ , μ•žμœΌλ‘œ μš”κ΅¬μ‚¬ν•­μ΄ λ°”λ€Œμ—ˆμ„ λ•Œ μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•  μˆ˜λ„ μ—†λ‹€. λ§Œμ•½ 크기, λͺ¨μ–‘, μΆœν•˜μ§€ λ“±μœΌλ‘œ 필터링 ν•˜κ³  μ‹Άλ‹€λ©΄ κ²°κ΅­ μ€‘λ³΅λœ ν•„ν„° λ©”μ„œλ“œλ₯Ό λ§Œλ“€κ±°λ‚˜, λͺ¨λ“  것을 μ²˜λ¦¬ν•˜λŠ” κ±°λŒ€ν•œ ν•˜λ‚˜μ˜ ν•„ν„° λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€.

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

ν”„λ ˆλ””μΌ€μ΄νŠΈ : μ°Έ λ˜λŠ” 거짓을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜

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

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 λ©”μ„œλ“œκ°€ λ‹€λ₯΄κ²Œ λ™μž‘ν•  것이라고 μ˜ˆμƒν•  수 있고, 이λ₯Ό μ „λž΅ λ””μžμΈ νŒ¨ν„΄ 이라고 ν•œλ‹€.

μ „λž΅ λ””μžμΈ νŒ¨ν„΄

각 μ•Œκ³ λ¦¬μ¦˜(μ „λž΅μ΄λΌ λΆˆλ¦¬λŠ”)을 μΊ‘μŠν™”ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜ νŒ¨λ°€λ¦¬λ₯Ό μ •μ˜ν•΄λ‘” λ‹€μŒμ— λŸ°νƒ€μž„μ— μ•Œκ³ λ¦¬μ¦˜μ„ μ„ νƒν•˜λŠ” 기법

μœ„μ—μ„œλŠ” ApplePredicateκ°€ μ•Œκ³ λ¦¬μ¦˜ νŒ¨λ°€λ¦¬μ΄κ³ , AppleHeavyWeightPredicate와 AppleGreenColorPredicateκ°€ μ „λž΅μ΄λ‹€.

이제 filterApplesμ—μ„œ ApplePredicate의 객체λ₯Ό λ°›μ•„ μ• ν”Œμ˜ 쑰건을 κ²€μ‚¬ν•˜λ„λ‘ λ©”μ„œλ“œλ₯Ό κ³ μ³μ•Όν•œλ‹€. μ΄λ ‡κ²Œ λ™μž‘ νŒŒλΌλ―Έν„°ν™”, 즉 λ©”μ„œλ“œκ°€ λ‹€μ–‘ν•œ λ™μž‘(λ˜λŠ” μ „λž΅)을 λ°›μ•„ λ‚΄λΆ€μ μœΌλ‘œ λ‹€μ–‘ν•œ λ™μž‘μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.

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

λ‹€μŒμ€ ApplePredicateλ₯Ό μ΄μš©ν•œ ν•„ν„° λ©”μ„œλ“œμ΄λ‹€.

1
2
3
4
5
6
7
8
9
10
public static List<Apple> filterApples(List<Apple> inventroy, **ApplePredicate p**) 
{
		List<Apple> result = new ArrayList<>();
		for (Apple apple : inventory) {
				if (p.test(apple)) {  // ν”„λ ˆλ””μΌ€μ΄νŠΈ 객체둜 사과 검사 쑰건을 μΊ‘μŠν™”
						result.add(apple);
				}
		}
		return result;
}

μ½”λ“œ/λ™μž‘ μ „λ‹¬ν•˜κΈ°

이제 λ†λΆ€μ˜ 검색 쑰건에 따라 ApplePredicateλ₯Ό 적절히 κ΅¬ν˜„ν•˜λŠ” 클래슀만 λ§Œλ“€λ©΄ λœλ‹€. 이제 Apple의 속성과 κ΄€λ ¨ν•œ λͺ¨λ“  변화에 λŒ€μ‘ν•  수 μžˆλŠ” μœ μ—°ν•œ μ½”λ“œλ₯Ό μ€€λΉ„ν•œ 것이닀.

150그램이 λ„˜λŠ” λΉ¨κ°„ 사과λ₯Ό 검색해달라

1
2
3
4
5
6
7
8
public class AppleRedAndHeavyPredicate implements ApplePredicate {
		public boolean test(Apple apple) {
				return RED.equals(apple.getColor()) && apple.getWeight() > 150;
		}
}

List<Apple> redAndHeeavyApples = 
		filterApples(inventory, new AppleRedAndHeavyPredicate());

μ „λ‹¬ν•œ ApplePredicate 객체에 μ˜ν•΄ filterApples λ©”μ„œλ“œμ˜ λ™μž‘μ΄ κ²°μ •λœλ‹€. 즉, filterApples λ©”μ„œλ“œμ˜ λ™μž‘μ„ νŒŒλΌλ―Έν„°ν™”ν•œ 것이닀.

filterApples λ©”μ„œλ“œμ˜ μƒˆλ‘œμš΄ λ™μž‘μ„ μ •μ˜ν•˜λŠ” 것이 test λ©”μ„œλ“œμ΄λ‹€. λ©”μ„œλ“œλŠ” 객체만 인수둜 λ°›μœΌλ―€λ‘œ test λ©”μ„œλ“œλ₯Ό ApplePredicate 객체둜 κ°μ‹Έμ„œ 전달해야 ν•œλ‹€.

ν•œ 개의 νŒŒλΌλ―Έν„°, λ‹€μ–‘ν•œ λ™μž‘

  • λ™μž‘ νŒŒλΌλ―Έν„°ν™”μ˜ 강점
    • μ»¬λ ‰μ…˜ 탐색 둜직과 각 ν•­λͺ©μ— μ μš©ν•  λ™μž‘μ„ 뢄리할 수 μžˆλ‹€.
    • ν•œ λ©”μ„œλ“œκ°€ λ‹€λ₯Έ λ™μž‘μ„ μˆ˜ν–‰ν•˜λ„λ‘ μž¬ν™œμš©ν•  수 μžˆλ‹€.

    • μœ μ—°ν•œ APIλ₯Ό λ§Œλ“€ 수 μžˆλ‹€.
  • Quiz. μœ μ—°ν•œ prettyPrintApple λ©”μ„œλ“œ κ΅¬ν˜„ν•˜κΈ°

    사과 리슀트λ₯Ό 인수둜 λ°›μ•„ λ‹€μ–‘ν•œ λ°©λ²•μœΌλ‘œ λ¬Έμžμ—΄μ„ 생성(μ»€μŠ€ν„°λ§ˆμ΄μ¦ˆλœ λ‹€μ–‘ν•œ toString λ©”μ„œλ“œμ™€ 같이)ν•  수 μžˆλ„λ‘ νŒŒλΌλ―Έν„°ν™”λœ prettyPrintApple λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜μ‹œμ˜€. 예λ₯Ό λ“€μ–΄ prettyPrintApple λ©”μ„œλ“œκ°€ 각각의 사과 무게λ₯Ό 좜λ ₯ν•˜λ„λ‘ μ§€μ‹œν•  수 μžˆλ‹€. ν˜Ήμ€ 각각의 사과가 λ¬΄κ±°μš΄μ§€ κ°€λ²Όμš΄μ§€ 좜λ ₯ν•˜λ„λ‘ μ§€μ‹œν•  수 μžˆλ‹€. prettyPrintApple λ©”μ„œλ“œλŠ” μ§€κΈˆκΉŒμ§€ μ‚΄νŽ΄λ³Έ 필터링 μ˜ˆμ œμ™€ λΉ„μŠ·ν•œ λ°©λ²•μœΌλ‘œ κ΅¬ν˜„ν•  수 μžˆλ‹€. μ’€ 더 μ‰½κ²Œ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλ„λ‘ λŒ€λž΅μ μΈ μ½”λ“œλ₯Ό κ³΅κ°œν•œλ‹€.

    1
    2
    3
    4
    5
    6
    
      public static void prettyPrintApple(List<Apple> inventory, ???) {
      		for (Apple apple: inventory) {
      				String output = ???.???(apple);
      				System.out.println(output);
      		}
      }
    
    • μ •λ‹΅

      μš°μ„  Apple을 인수둜 λ°›μ•„ 정해진 λ¬Έμžμ—΄λ‘œ λ°˜ν™˜ν•  μˆ˜λ‹¨μ΄ μžˆμ–΄μ•Ό ν•œλ‹€. ApplePredicate μΈν„°νŽ˜μ΄μŠ€λ₯Ό μƒκ°ν•΄λ³΄μž.

      1
      2
      3
      
        public interface AppleFormatter {
        		String accept(Apple a);
        }
      

      이제 AppleFormatter μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄ μ—¬λŸ¬ 포맷 λ™μž‘μ„ λ§Œλ“€ 수 μžˆλ‹€.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        public class AppleFancyFormatter implements AppleFormatter {
        		public String accept(Apple apple) {
        				String characteristic = apple.getWeight() > 150 ? "heavy" :
        						"light";
        				return "A " + characteristic + " " + apple.getColor() + " apple";
        }
              
        public class AppleSimpleFormatter implements AppleFormatter(
        		public String accept(Apple apple) {
        				return "An apple of " + apple.getWeight() + "g";
        		}
        }
      

      λ§ˆμ§€λ§‰μœΌλ‘œ prettyPrintApple λ©”μ„œλ“œκ°€ AppleFormatter 객체λ₯Ό 인수둜 λ°›μ•„ λ‚΄λΆ€μ μœΌλ‘œ μ‚¬μš©ν•˜λ„λ‘ μ§€μ‹œν•œλ‹€. 즉, prettyPrintApple에 νŒŒλΌλ―Έν„°λ₯Ό μΆ”κ°€ν•œλ‹€.

      1
      2
      3
      4
      5
      6
      7
      
        public static void prettyPrintApple(List<Apple> inventory, 
        																		AppleFormatter formatter) {
        		for (Apple apple : inventory) {
        				String output = formatter.accept(apple);
        				System.out.println(output);
        		}
        }
      

      이제 λ‹€μ–‘ν•œ λ™μž‘μ„ prettyPrintApple λ©”μ„œλ“œλ‘œ 전달할 수 μžˆλ‹€. AppleFormatter의 κ΅¬ν˜„μ„ κ°μ²΄ν™”ν•œ λ‹€μŒμ— prettyPrintApple의 인수둜 μ „λ‹¬ν•œλ‹€.

      1
      
        prettyPrintAppple(inventory, new AppleFancyFormatter());
      

      μ½”λ“œ μ‹€ν–‰ κ²°κ³ΌλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

      1
      2
      
        A light green apple
        A heavy red apple 
      

      λ˜λŠ” λ‹€μŒκ³Ό 같이 κ΅¬ν˜„ν•œλ‹€.

      1
      
        prettyPrintApple(inventory, new AppleSimpleFormatter());
      

      λ‹€μŒμ€ μ½”λ“œ μ‹€ν–‰ 결과이닀.

      1
      2
      
        An apple of 80g
        An apple of 155g
      

λ™μž‘μ„ 좔상화 ν•˜μ—¬ λ³€ν™”ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ— λŒ€μ‘ν•˜λŠ” μ½”λ“œλ₯Ό κ΅¬ν˜„ν–ˆμ§€λ§Œ, μ—¬λŸ¬ 클래슀λ₯Ό κ΅¬ν˜„ν•΄μ„œ μΈμŠ€ν„΄μŠ€ν™”ν•˜λŠ” 과정을 κ°œμ„ ν•  방법을 μ•Œμ•„λ³΄μž.

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

  • [ λ™μž‘ νŒŒλΌλ―Έν„°ν™” : ν”„λ ˆλ””μΌ€μ΄νŠΈλ‘œ 사과 필터링 ] 예제

    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
    32
    33
    34
    35
    36
    
      // 무거운 사과 선택
      public class AppleHeavyWeightPreidicate implements ApplePredicate {
      		public boolean test(Apple apple) {
      				return apple.getWeight() > 150;
      		}
      }
        
      // 녹색 사과 선택
      public class AppleGreenColorPredicate implements ApplePredicate {
      		public boolean test(Apple apple) {
      				return GREEN.equals(apple.getColor());
      		}
      }
        
      public class FilteringApples {
      		public static void main(String...args) {
      				List<Apple> inventory = Arrays.asList(new Apple(80, GREEN),
      																							new Apple(155, GREEN),
      																							new Apple(120, RED));
      				List<Apple> heavyApples =  // κ²°κ³Ό 리슀트느 155그램의 사과 ν•œκ°œλ₯Ό ν¬ν•¨ν•œλ‹€. 
      						filterApples(inventory, new AppleHeavyWeightPredicate());
      				List<Apple> greenApples =  // κ²°κ³Ό λ¦¬μŠ€νŠΈλŠ” 녹색 사과 두 개λ₯Ό ν¬ν•¨ν•œλ‹€.
      						filterApples(inventory, new AppleGreenColorPredicate());
      		}
        
      		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;
      		}
      }
    

    둜직과 κ΄€λ ¨ μ—†λŠ” μ½”λ“œκ°€ 많이 μΆ”κ°€λ˜μ–΄μžˆλ‹€.

μžλ°”λŠ” 클래슀의 μ„ μ–Έκ³Ό μΈμŠ€ν„΄μŠ€ν™”λ₯Ό λ™μ‹œμ— μˆ˜ν–‰ν•  수 μžˆλ„λ‘ 읡λͺ… ν΄λž˜μŠ€λΌλŠ” 기법을 μ œκ³΅ν•œλ‹€. 읡λͺ… 클래슀λ₯Ό μ΄μš©ν•˜λ©΄ μ½”λ“œμ˜ 양을 쀄일 수 μžˆλ‹€. (ν•˜μ§€λ§Œ λžŒλ‹€ ν‘œν˜„μ‹μ„ μ‚¬μš©ν•  μˆ˜λ„ 있음)

2.3.1 읡λͺ… 클래슀

μžλ°”μ˜ 지역 클래슀(블둝 내뢀에 μ„ μ–Έλœ 클래슀)와 λΉ„μŠ·ν•œ κ°œλ…μœΌλ‘œ 말 κ·ΈλŒ€λ‘œ 이름이 μ—†λŠ” ν΄λž˜μŠ€λ‹€.

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

즉, μ¦‰μ„μ—μ„œ ν•„μš”ν•œ κ΅¬ν˜„μ„ λ§Œλ“€μ–΄ μ‚¬μš©ν•  수 μžˆλ‹€.

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

λ‹€μŒμ€ 읡λͺ… 클래슀λ₯Ό μ΄μš©ν•΄μ„œ ApplePredicateλ₯Ό κ΅¬ν˜„ν•˜λŠ” 객체λ₯Ό λ§Œλ“œλŠ” λ°©λ²•μœΌλ‘œ 필터링 예제λ₯Ό λ‹€μ‹œ κ΅¬ν˜„ν•œ μ½”λ“œλ‹€.

1
2
3
4
5
6
List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
		// filterApples λ©”μ„œλ“œμ˜ λ™μž‘μ„ 직접 νŒŒλΌλ―Έν„°ν™” ν–ˆλ‹€!
		public boolean test(Apple apple) {
				return RED.equals(apple.getColor());
		}
}

GUI μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 이벀트 ν•Έλ“€λŸ¬ 객체λ₯Ό κ΅¬ν˜„ν•  λ•Œ 읡λͺ… ν΄λž˜μŠ€κ°€ μ’…μ’… μ‚¬μš©λœλ‹€.

  • 읡λͺ… 클래슀의 λΆ€μ‘±ν•œ 점
    • λ§Žμ€ 곡간 차지

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
        List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
        		public boolean test(Apple a) {
        				return RED.equals(a.getColor());
        		}
        });
        button.setOnAction(new EventHandler<ActionEvent>() {
        		public void handle(ActionEvent event) {
        				System.out.println("Whoooo a click!!");
        		}
        }
      

      μ½”λ“œκ°€ λ°˜λ³΅λ˜μ–΄ μ§€μ €λΆ„ν•˜λ‹€.

    • λ§Žμ€ ν”„λ‘œκ·Έλž˜λ¨Έκ°€ 읡λͺ… 클래슀 μ‚¬μš©μ— μ΅μˆ™ν•˜μ§€ μ•Šλ‹€.

      μž₯ν™©ν•œ μ½”λ“œλŠ” κ΅¬ν˜„ν•˜κ³  μœ μ§€λ³΄μˆ˜ν•˜λŠ” 데 μ‹œκ°„μ΄ 였래 걸릴 뿐 μ•„λ‹ˆλΌ μ½λŠ” 즐거움도 λΊλŠ”λ‹€.

      ν•œ λˆˆμ— 이해할 수 μžˆμ–΄μ•Ό 쒋은 μ½”λ“œλ‹€.

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

μžλ°” 8의 λžŒλ‹€ ν‘œν˜„μ‹μ„ μœ„ν•΄ 이전 예제 μ½”λ“œλ₯Ό κ°„λ‹¨ν•˜κ²Œ μž¬κ΅¬ν˜„ν•  수 μžˆλ‹€.

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

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

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

public static <T> List<T> filter(List<T> list, Predicate<T> p) {//ν˜•μ‹ νŒŒλΌλ―Έν„° pλ“±μž₯
		List<T> result = new ArrayList<>();
		for (T e: list) {
				if (p.test(e)) {
						result.add(e);
				}
		}
		return result;
}

λ‹€μŒμ€ λžŒλ‹€ ν‘œν˜„μ‹μ„ μ‚¬μš©ν•œ μ˜ˆμ œλ‹€.

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);

μžλ°” 8 이후뢀터 κ°€λŠ₯ν•œ μ½”λ“œμ΄λ‹€.

2.4 μ‹€μ „ 예제

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

μžλ°” 8의 Listμ—λŠ” sort λ©”μ„œλ“œκ°€ ν¬ν•¨λ˜μ–΄ μžˆλ‹€(λ¬Όλ‘  Collections.sort도 쑴재).

λ‹€μŒκ³Ό 같은 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ°–λŠ” java.util.Comparator 객체λ₯Ό μ΄μš©ν•΄μ„œ sort의 λ™μž‘μ„ νŒŒλΌλ―Έν„°ν™” ν•  수 μžˆλ‹€.

1
2
3
4
// java.util.Comparator
public interface Comparator<T> {
		int compare(T o1, T o2);
}

Comparatorλ₯Ό κ΅¬ν˜„ν•΄μ„œ sort λ©”μ„œλ“œμ˜ λ™μž‘μ„ λ‹€μ–‘ν™”ν•  수 μžˆλ‹€.

  1. 읡λͺ… 클래슀λ₯Ό μ΄μš©ν•΄ λ¬΄κ²Œκ°€ 적은 μˆœμ„œλ‘œ 사과λ₯Ό μ •λ ¬

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

    μš”κ΅¬μ‚¬ν•­μ΄ λ³€κ²½λ˜λ©΄ μƒˆλ‘œμš΄ μš”κ΅¬μ‚¬ν•­μ— λ§žλŠ” Comparator을 λ§Œλ“€μ–΄ sort에 μ „λ‹¬ν•œλ‹€.

  2. λžŒλ‹€ ν‘œν˜„μ‹μœΌλ‘œ λ³€κ²½

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

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

μžλ°” μŠ€λ ˆλ“œλ₯Ό μ΄μš©ν•˜λ©΄ λ³‘λ ¬λ‘œ μ½”λ“œ 블둝을 μ‹€ν–‰ν•  수 μžˆλ‹€.

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

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

1
2
3
4
// java.lang.Runnable
public interface Runnable {
		void run();
} // μ½”λ“œ 블둝 μ‹€ν–‰ κ²°κ³Ό void

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을 결과둜 λ°˜ν™˜ν•˜κΈ°

  • ExecutorService(μΈν„°νŽ˜μ΄μŠ€)
    • μžλ°” 5λΆ€ν„° μ§€μ›ν•˜λŠ” 좔상화 κ°œλ…
    • νƒœμŠ€ν¬ 제좜과 μ‹€ν–‰ κ³Όμ •μ˜ 연관성을 λŠμ–΄μ€Œ
    • νƒœμŠ€ν¬λ₯Ό μŠ€λ ˆλ“œ ν’€λ‘œ 보내고 κ²°κ³Όλ₯Ό Future둜 μ €μž₯ κ°€λŠ₯(μŠ€λ ˆλ“œμ™€ Runnable을 μ΄μš©ν•˜λŠ” 방식과 닀름)

Callable μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•΄ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λŠ” νƒœμŠ€ν¬λ₯Ό λ§Œλ“ λ‹€. (Runnable의 μ—…κ·Έλ ˆμ΄λ“œ 버전)

1
2
3
4
// java.util.concurrent.Callable
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
Button button = new Button("Send");
button.setOnAction(new EventHandler<ActionEvent>() {
		public void handle(ActionEvent event) {
				label.setText("Sent!!");
		}
});

즉, EventHandlerλŠ” setOnAction λ©”μ„œλ“œμ˜ λ™μž‘μ„ νŒŒλΌλ―Έν„°ν™”ν•œλ‹€. λžŒλ‹€ν‘œν˜„μ‹μ€ λ‹€μŒκ³Ό κ°™λ‹€.

1
button.setOnAction((ActionEvent event) -> label.setText("Sent!!"));

2.5 마치며

  • λ™μž‘ νŒŒλΌλ―Έν„°ν™”μ—μ„œλŠ” λ©”μ„œλ“œ λ‚΄λΆ€μ μœΌλ‘œ λ‹€μ–‘ν•œ λ™μž‘μ„ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ μ½”λ“œλ₯Ό λ©”μ„œλ“œ 인수둜 μ „λ‹¬ν•œλ‹€.
  • λ™μž‘ νŒŒλΌλ―Έν„°ν™”λ₯Ό μ΄μš©ν•˜λ©΄ λ³€ν™”ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ— 더 잘 λŒ€μ‘ν•  수 μžˆλŠ” μ½”λ“œλ₯Ό κ΅¬ν˜„ν•  수 있으며 λ‚˜μ€‘μ— μ—”μ§€λ‹ˆμ–΄λ§ λΉ„μš©μ„ 쀄일 수 μžˆλ‹€.
  • μ½”λ“œ 전달 기법을 μ΄μš©ν•˜λ©΄ λ™μž‘μ„ λ©”μ„œλ“œμ˜ 인수둜 전달할 수 μžˆλ‹€. ν•˜μ§€λ§Œ μžλ°” 8 μ΄μ „μ—λŠ” μ½”λ“œλ₯Ό μ§€μ €λΆ„ν•˜κ²Œ κ΅¬ν˜„ν•΄μ•Ό ν–ˆλ‹€. 읡λͺ… ν΄λž˜μŠ€λ‘œλ„ μ–΄λŠ 정도 μ½”λ“œλ₯Ό κΉ”λ”ν•˜κ²Œ λ§Œλ“€ 수 μžˆμ§€λ§Œ μžλ°” 8μ—μ„œλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό 상속받아 μ—¬λŸ¬ 클래슀λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•˜λŠ” 수고λ₯Ό 없앨 수 μžˆλŠ” 방법을 μ œκ³΅ν•œλ‹€.
  • μžλ°” API의 λ§Žμ€ λ©”μ„œλ“œλŠ” μ •λ ¬, μŠ€λ ˆλ“œ, GUI 처리 등을 ν¬ν•¨ν•œ λ‹€μ–‘ν•œ λ™μž‘μœΌλ‘œ νŒŒλΌλ―Έν„°ν™”ν•  수 μžˆλ‹€.
This post is licensed under CC BY 4.0 by the author.