kangchanguk / study

0 stars 0 forks source link

chapter2 #3

Open kangchanguk opened 2 years ago

kangchanguk commented 2 years ago

동적 파라미터화 코드 전달하기

변화에 대응하는 코드

기존의 농장 재고목록 애플리케이션에 리스트에서 녹색사과만 필터링 하는 기능을 추가

1. 녹색 사과 필터링

2. 색을 파라미터화, 무게를 파라미터화

2-1) 색을 파라미터 화

public static List<Apple> filterGreenApples(List<Apple> inventory,  Color color) {
      List<Apple> result = new ArrayList<>();
      for (Apple apple : inventory) {
          if (color.equals(apple.getColor())) {
              result.add(apple);
          }
      }
      return result;
}

2-2) 무게를 파라미터화

public static List<Apple> filterGreenApples(List<Apple> inventory,  int weight) {
      List<Apple> result = new ArrayList<>();
      for (Apple apple : inventory) {
          if (apple.getWeight() > weight) {
              result.add(apple);
          }
      }
      return result;
}

BUT!!! 필터링을 적용하는 부분이 대부분 중복된다. 소프트웨어 공학의 DRY(don't repeat yourself)원칙을 위배하는 것

여러조건들이 추가될 때마다 새로운 메소드를 만드는 것은 비효율적이다. => 동작 파라미터화를 사용한다.

1.동작 파라미터

public interface ApplePredicate {
    boolean test(Apple apple);
}
스크린샷 2022-02-09 오후 5 32 57

인터페이스를 정의하고 참 또는 거짓을 반환하는 함수(predicate)를 구현한다.

전략 디자인 패턴: 각 알고리즘을 캡슐화하는 알고리즘 패밀리를 정의해 둔 다음에 런타임에 알고리즘을 선택하는 기법(ApplePredicate: 알고리즘 패밀리, AppleHeavyWeightPredicate: 알고리즘)

ApplePredicate 객체를 받아서 애플의 조건을 검사하도록 매소드를 고치면 매서드가 다양한 동작을 받아서 내부적으로 다양한 동작을 수행할 수 있도록 하는 동작 파라미터화가 가능해짐

2.추상적인 조건으로 필터링

public static List<Apple> filterGreenApples(List<Apple> inventory,  ApplePredicate P) {
      List<Apple> result = new ArrayList<>();
      for (Apple apple : inventory) {
          if (p.test(apple)) {
              result.add(apple);
          }
      }
      return result;
}

ex) 무게와 색상를 기준으로 필터링하는 메소드일 시 해당 기준으로 필터링하는 ApplePredicate 객체를 생성한 뒤 filterApples 메서드에 전달한다.

스크린샷 2022-02-09 오후 5 37 05
package pdms.pdmstool.service;

public class Practice {

    public static void prettyPrintApple(List<Apple> inventory, AppleFormatter AppleFancyFormatter ){
        for(Apple apple: inventory){
            String output = ();
            System.out.println(output);
        }
    }

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

    public class AppleFancyFormatter implements AppleFormatter{
        public String accept(Apple apple){
            String characteristic = apple.getWeight() > 150 ? "heavy": "light";
            return characteristic;
        }

    }

    public class AppleSimpleFormatter implements AppleFormatter{
        public String accept(Apple apple){
            return (String)apple.getWeight();
        }
    }
}

위처럼 메서드로 새로운 동작을 전달하려면 ApplePredicate 인터페이스를 구현한 여러 클래스를 정의한 다음에 인스턴스화 해야하는데 이는 상당히 번거로운 작업이다!!

3. 익명클래스(클래스 선언과 인스턴스화를 동시에 수행)

이름없는 클래스를 선언해서 클래스 선언과 인스턴스화를 동시에 수행한다. 그러나 익명클래스 역시 많은 줄을 차지한다!!

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

### 4. 람다 표현식 사용

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


### 실전 예제

동작 파라미터화가 변화하는 요구사항에 쉽게 적응하는 유용한 패턴 => 동작을 캡슐화한 다음에 메서드로 전달해서 메서드의 동작을 파라미터화한다.

#### 1. comparator로 정렬하기

자바 리스트에는 sort 메서드가 포함되어 있다. Comparator 객체를 이용해서 sort의 동작을 파라미터화 하겠다!!

inventory.sort(new Comparator(Apple){ public int compare(Apple a1, Apple aw){ return a1.getWeight().compareTo(a2.getWeight())); } } });


람다를 사용한다면

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


#### 2. Runnable로 코드 블록 실행하기

자바 스레드를 활용하면 병렬로 코드 블록을 실행 할 수 있다.

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


#### 3.callable을 결과로 반환하기

Future threadName = executorService.submit(()-> Thread.currentThread().getName());


#### 4. GUI 이벤트 처리하기

setOnAction 메소드에 EventHandler를 전달함으로써 이벤트에 어떻게 반응할 지 설정할 수 있다.

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