Skip to content

Latest commit

 

History

History
179 lines (129 loc) · 5.24 KB

02-동작 파라미터화.md

File metadata and controls

179 lines (129 loc) · 5.24 KB

동작 파라미터화 란?

아직은 어떻게 실행할 것인지 결정되지 않은 코드 블록.

  • 장점 : 한 메소드가 여러 동작을 수행할 수 있도록 함, 동작을 로직과 분리하여 유연한 API를 만들 수 있다.

2-1. 변화하는 요구사항에 대응하기

👩‍🌾 기획자 : 녹색 사과만 필터링 → 빨간 사과도 필터링

enum Color = { RED , GREEN, YELLOW }

// 🔥
public static List<Apple> filterAppleByColor(List<Apple> inventory, Color color){
	List<Apple> result = new ArrayList<>;

	for (Apple apple: inventory){
		if (apple.getColor().equals(color){
			return result.add(apple);
		}
	}
}

👩‍🌾 기획자 : 색 외에도 무게도 필터링해주셨으면 좋겠습니다.

👩‍💻 개발자: (미리미리 좀 말하란 말이야....무게 정보 필터 메소드도 하나 만들어야겠다.)

public static List<Apple> filterAppleByWeight(List<Apple> inventory, int weight){
	List<Apple> result = new ArrayList<>;

	for (Apple apple: inventory){
		if (apple.getWeight() > weight){
			return result.add(apple);
		}
	}
}

⇒ 이러고 나니 색 필터링과 무게 필터링 코드가 한 줄 빼고 다 비슷해졌다. 들여다보고 있자니 굉장히 불편해지는 상황이다.

2-2. 동적 파라미터화

boolean 값을 반환하는 함수를 Predicate 라고 한다. 선택 조건을 결정하는 인터페이스를 하나 정의해보자.

public interface ApplePredicate{
	boolean condition(Apple apple);
}

그리고 색과 무게를 체크하는 클래스를 각각 만들어본다.

// 1. 무거운 사과만 선택
public class AppleHeavyWeightPredicate implements ApplePredicate{
	public boolean condition(Apple apple){
		return apple.getWeight() > 150;
	}
}
// 2. 초록색 사과만 선택
public class AppleGreenColorPredicate implements ApplePredicate{
	public boolean condition(Apple apple){
		return GREEN.equals(apple.getColor);
	}
}

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c981065a-c596-4197-85fc-356403867af3/IMG_3943.jpg

전략 디자인 패턴 : 패턴화하는 알고리즘 패밀리를 정의해놓고, 런타임 시에 선택하여 사용한다.

→ 이제 메소드가 다양한 동작을 받아서 내부적으로 수행할 수 있게 되었고, 예제를 보면 predicate 객체로 사과 검색 조건을 캡슐화하였다.

즉, 넘겨주는 ApplePredicate 객체에 따라 filtersApple 메소드의 "동작"이 결정된다. 즉, 동작을 "파라미터화" 한 것이다.

// 🔥v2
public static List<Apple> filterAppleByWeight(List<Apple> inventory, ApplePredicate p){
	List<Apple> result = new ArrayList<>;

	for (Apple apple: inventory){
		if (p.condition(apple)){
			return result.add(pple);
		}
	}
}

메서드는 객체만 인수로 받기 때문에 condition 메소드를 ApplePredicate로 감싸서 전달한 것이다.

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/ac1b853c-a246-49fa-b37a-2fb781bd4a30/IMG_6D01245FF47F-1.jpeg

2-3. 익명 클래스

여러 클래스들을 생성하고 인스턴스화하는 과정이 조금 귀찮게 느껴질 수 있다. 이 부분을 개선하기 위해 익명 클래스가 필요하다.

익명 클래스 : 클래스 선언과 인스턴스화를 동시에 수행할 수 있음

List<Apple> redApples = filterApples(inventory, new ApplePredicate(){
	public boolean condition(Apple apple){
		return RED.equals(apple.getColor());
	}
}

2-4. 람다 표현식 👍

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

혹은 리스트 형식으로 추상화하여 사과 말고도 바나나, 오렌지, 문자열 등 다양한 타입의 리스트에도 쓸 수 있다.

public interface Predicate<T>{
	boolean condition(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.condition(e){
			result.add(e);
		}
	}
	return result;
}

이를 사용한 예시는 다음과 같다.

List<Apple> redApples = filter(inventory, (Apple apple) 
								-> GREEN.equals(apple.getColor()));

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

2-5. 실전 예제

동작 파라미터화는 즉, 동작을 캡슐화 한 다음 메소드로 전달해서! 메소드의 동작을 파라미터화 하는 것을 말한다.

Comparator : 정렬

public interface Comparator<T>{
	int compare(T o1, T o2);
}
inventory.sort( (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

Runnable : 코드 블록 실행

자바 쓰레드를 사용하면 병렬로 코드블록을 실행할 수 있다. Runnable 인터페이스를 이용해서 실행할 코드블록을 지정해보자.

Thread t = new Thread(new Runnable() {
   public void run(){
			System.out.println("Hello world!");
	}
})

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