더 즐겁고 행복하게 일할려면..
- 자기가 하고 싶은것만 하자
- 하지만 현실에선 힘들다.
- 일(노동) 자체에 부정적인 시각이 있다.
- 일을 자아실현의 도구로 생각하자.
자동차 경주 게임 구현
인터페이스, 익명클래스, 람다 연습
- 모든 수의 합을 구하는 메서드
public int sumAll(List<Integer> numbers) { int total = 0; for (int number : numbers) { total += number; } return total; }
- 짝수의 합을 구하는 메서드
public int sumAllEven(List<Integer> numbers) { int total = 0; for (int number : numbers) { if (number % 2 == 0) { total += number; } } return total; }
- 위의 두 메서드가 구현되어 있는 상황에서 List에 담긴 값중 3보다 큰 수만을 더해야 하는 메서드를 구현해야한다.
public int sumOverThree(List<Integer> numbers) { int total = 0; for (int number : numbers) { if (number > 2) { total += number; } } return total; }
- 위 3개의 메서드에서 많은 중복이 발생한다. 중복을 제거해 보자.
- 변경되는 부분과 변경되지 않는 부분의 코드를 분리한다.
- 변경되지 않는 부분
int total = 0; for (int number : numbers) { // if문을 제외한 부분은 변경이 일어나지 않는다. total += number; } return total;
- 변경되는 부분
for (...) { if (number > 2) { -> if의 조건문에서 변경이 일어난다. ... } }
- 변경되는 부분을 인터페이스로 추출해보자.
public interface AddStrategy { boolean addNumber(int number); }
- 인터페이스로 공통된 부분을 추출하면 인터페이스의 구현클래스를 생성해야한다.
- 기본 합의 조건을 구하는 구현클래스
public class DefaultSum implements AddStrategy { @Override boolean addNumber(int number) { return true; } }
- 짝수의 합의 조건을 구하는 구현 클래스
public class EvenSum implements AddStrategy { @Override boolean addNumber(int number) { return (number%2 == 0); } }
- 3보다 큰 수의 조건을 구하는 구현 클래스
public class OverThreeSum implements AddStrategy { @Override boolean addNumber(int number) { return (number > 3); } }
- 구현된 클래스를 인터페이스를 이용해 적용해 보자.
public int sum(List<Integer> numbers, AddStrategy addStrategy) { int total = 0; for (int number : numbers) { if (addStrategy.addNumber(number)) { total += number; } } return total; } public int sumAll(List<Integer> numbers) { return sum(numbers, new DefaultSum()); } public int sumAllEven(List<Integer> numbers) { return sum(numbers, new EvenSum()); } public int sumOverThree(List<Integer> numbers) { return sum(numbers, new OverThreeSum()); }
-
인터페이스를 이용해서 중복을 뽑아 낸다고 코드 수가 줄어드는 것이 아니다.
-
단지 공통기능부분에서 조금 다른 부분의 코드를 공통되게 적용할 수 있게 하는것이다.
- 하지만 인터페이스를 이용한 구현클래스의 수가 늘어날수록 클래수의 수가 기하급수적으로 많아진다.
- 이를 해결하기 위해서 익명클래스를 이용하여 인터페이스를 구현할 수 있다.
-
익명클래스를 이용해 구현클래스를 이용하지않고 인터페이스를 구현할 수 있다.
public int sum(List<Integer> numbers, AddStrategy addStrategy) { int total = 0; for (int number : numbers) { if (addStrategy.addNumber(number)) { total += number; } } return total; } public int sumAll(List<Integer> numbers) { return sum(numbers, new AddStrategy() { @Override public boolean addNumber(int number) { return true; } }); } public int sumAllEven(List<Integer> numbers) { return sum(numbers, new AddStrategy() { @Override public boolean addNumber(int number) { return number %2 == 0; } }); } public int sumOverThree(List<Integer> numbers) { return sum(numbers, new AddStrategy() { @Override public boolean addNumber(int number) { return number > 3; } }); }
- 익명클래스를 이용해 인터페이스를 구현하면 코드가 매우 지저분해지는 것을 볼 수 있다.
- 이를 해결하기위해 자바8에서는 람다식이 존재한다.
- 람다식을 사용하기위해서는 인터페이스에 메서드가 단 하나만 존재해야 사용가능하다.
-
예시
package study; public interface AddStrategy { boolean addNumber(int number); // boolean Number(int number); -> 주석을 풀 시 프로덕션 코드에서 에러가 발생한다. }
-
람다식을 이용한 인터페이스의 구현
public int sum(List<Integer> numbers, AddStrategy addStrategy) { int total = 0; for (int number : numbers) { if (addStrategy.addNumber(number)) { total += number; } } return total; } public int sumAllLamda(List<Integer> numbers) { return sum(numbers, (a) -> true); } public int sumAllEvenLamda(List<Integer> numbers) { return sum(numbers, (a) -> a % 2 == 0); } public int sumOverThreeLamda(List<Integer> numbers) { return sum(numbers, (a) -> a > 3); }
- 람다식을 이용하면 인터페이스의 구현부가 엄청나게 간단해 진 것을 볼 수 있다.
-
람다식의 사용법을 이렇다.
// 인터페이스를 매개인자로 받는 변하지않는 공통 부분 public int sum(List<Integer> numbers, AddStrategy addStrategy) { int total = 0; for (int number : numbers) { if (addStrategy.addNumber(number)) { total += number; } } return total; } ... // 인터페이스를 적용할 메서드 public int sumOverThreeLamda(List<Integer> numbers) { return sum(numbers, (a) -> a > 3); //인터페이스의 매개인자 부분에 (매개인자) -> (조건문) 을 입력한다. }
- 여기서 (매개인자) ->(화살표) (결과값) 의 형식을 지켜야한다.
-
결과값을 매개인자의 리턴값을 표시해야한다. boolean이면 참/거짓을 String이면 문자열을 입력해야한다. 리턴값과 다른 타입을 입력하면 컴파일 오류가 발생한다.
- 인터페이스, 익명클래스, 람다와 스트림의 자바8의 꽃이라 할 수 있는 부분이다. 반드시 익혀두자
Comments