본문 바로가기
java

Java 8 동작 파라미터화 코드전달하기

by chunkind 2023. 11. 28.
반응형

공통 코드

Enum

public enum Color {
	GREEN, RED, BLUE, YELLOW, WHITE, BLACK
}

VO

public class Apple{
	private Color color;
	private int weight;
	
	public Apple(Color color) {
		this.color = color;
	}
	public Apple(Color color, int weight) {
		this.color = color;
		this.weight = weight;
	}
	
	public Color getColor() {
		return color;
	}
	public void setColor(Color color) {
		this.color = color;
	}
	public int getWeight() {
		return weight;
	}
	public void setWeight(int weight) {
		this.weight = weight;
	}
	@Override
	public String toString() {
		return "Apple [color=" + color + ", weight=" + weight + "]";
	}
}

 

녹색 사과만 필터하는 로직

public class TestCase01 {
	public static final Color GREEN = Color.GREEN;
	public static final Color RED = Color.RED;
	public static final Color BLUE = Color.BLUE;
	public static final Color YELLOW = Color.YELLOW;
	public static final Color WHITE = Color.WHITE;
	public static final Color BLACK = Color.BLACK;
	
	public static List<Apple> filterGreenApples(List<Apple> inventory){
		List<Apple> result = new ArrayList<Apple>();
		for(Apple apple: inventory) {
			if(GREEN.equals(apple.getColor())) {
				result.add(apple);
			}
		}
		return result;
	}
	
	public static void main(String[] args) {
		List<Apple> inventory = new ArrayList<Apple>();
		inventory.add(new Apple(Color.GREEN));
		inventory.add(new Apple(Color.RED));
		inventory.add(new Apple(Color.BLUE));
		inventory.add(new Apple(Color.YELLOW));
		inventory.add(new Apple(Color.WHITE));
		inventory.add(new Apple(Color.BLACK));
		
		List<Apple> result = filterGreenApples(inventory);
		System.out.println(result.toString());
	}
}

 

모든 사과를 inventory에 담아서 GREEN사과만 필터하여 result에 저장하고 출력하는 로직이다.

이로직은 오직 GREEN 사과만 담을수 밖에없다.

 

다양한색을 필터 처리 하도록 수정

public class TestCase02 {
	public static final Color GREEN = Color.GREEN;
	public static final Color RED = Color.RED;
	public static final Color BLUE = Color.BLUE;
	public static final Color YELLOW = Color.YELLOW;
	public static final Color WHITE = Color.WHITE;
	public static final Color BLACK = Color.BLACK;
	
	public static List<Apple> filterGreenApples(List<Apple> inventory, Color color){
		List<Apple> result = new ArrayList<Apple>();
		for(Apple apple: inventory) {
			if(color.equals(apple.getColor())) {
				result.add(apple);
			}
		}
		return result;
	}
	
	public static void main(String[] args) {
		List<Apple> inventory = new ArrayList<Apple>();
		inventory.add(new Apple(Color.GREEN));
		inventory.add(new Apple(Color.RED));
		inventory.add(new Apple(Color.BLUE));
		inventory.add(new Apple(Color.YELLOW));
		inventory.add(new Apple(Color.WHITE));
		inventory.add(new Apple(Color.BLACK));
		
		List<Apple> result = filterGreenApples(inventory, GREEN);
		System.out.println(result.toString());
	}
}

 

Color Enum을 파라미터로 추가하여 필터하고 싶은 색을 인자값으로 전달하고 그결과를 받는다. 이전 로직보다는 유연한 코드지만, 무게를 필터한다던가 다른사항을 필터하기엔 부족한 프로그램이라 볼 수 있다.

무게도 필터링하는 기능 추가

public class TestCase04 {
	public static final Color GREEN = Color.GREEN;
	public static final Color RED = Color.RED;
	public static final Color BLUE = Color.BLUE;
	public static final Color YELLOW = Color.YELLOW;
	public static final Color WHITE = Color.WHITE;
	public static final Color BLACK = Color.BLACK;

	public static List<Apple> filter(List<Apple> inventory, Color color, int weight, boolean flag){
		List<Apple> result = new ArrayList<Apple>();
		for(Apple apple: inventory) {
			if((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight)) {
				result.add(apple);
			}
		}
		return result;
	}
	
	public static void main(String[] args) {
		List<Apple> inventory = Arrays.asList(
			 new Apple(Color.GREEN, 10)
			,new Apple(Color.RED, 50)
			,new Apple(Color.BLUE, 100)
			,new Apple(Color.YELLOW, 150)
			,new Apple(Color.WHITE, 200)
			,new Apple(Color.BLACK, 100)
			,new Apple(Color.GREEN, 100)
			,new Apple(Color.GREEN, 150)
		);
		
		List<Apple> result = filter(inventory, GREEN, 0, true);
		List<Apple> result2 = filter(inventory, null, 150, false);
		System.out.println(result.toString());
		System.out.println(result2.toString());
	}
}

 

무게를 필터하는 로직을 추가 하였다. 메서드의 기능이 추가됨에 따라 filterGreenApples 가 아니라 filter이다.

기능이 늘어남에 따라 true/false를 구분 짓는 인자값또한 추가되었다. 코드도 지저분하고 클라이언트에 true, false로 요청하를 로직에서 무엇때문에 true, false를 넣는지 직관적이지 않다. 기능이 늘어남에따라 로직이 더러워질 것이 뻔한 코드다.

인터페이스로 추상화하여 구상 클래스로 구현

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

public class AppleGreenColorPredicate implements ApplePredicate{
	@Override
	public boolean test(Apple apple) {
		return TestCase05.GREEN.equals(apple.getColor());
	}
}

public class AppleHeavyWeightPredicate implements ApplePredicate{
	@Override
	public boolean test(Apple apple) {
		return apple.getWeight() > 150;
	}
}

 

public class TestCase05 {
	public static final Color GREEN = Color.GREEN;
	public static final Color RED = Color.RED;
	public static final Color BLUE = Color.BLUE;
	public static final Color YELLOW = Color.YELLOW;
	public static final Color WHITE = Color.WHITE;
	public static final Color BLACK = Color.BLACK;
	
	public static List<Apple> filter(List<Apple> inventory, ApplePredicate p){
		List<Apple> result = new ArrayList<Apple>();
		for(Apple apple: inventory) {
			if(p.test(apple)) {
				result.add(apple);
			}
		}
		return result;
	}
	
	public static void main(String[] args) {
		List<Apple> inventory = Arrays.asList(
			 new Apple(Color.GREEN, 10)
			,new Apple(Color.RED, 50)
			,new Apple(Color.BLUE, 100)
			,new Apple(Color.YELLOW, 150)
			,new Apple(Color.WHITE, 200)
			,new Apple(Color.BLACK, 100)
			,new Apple(Color.GREEN, 100)
			,new Apple(Color.GREEN, 150)
		);
		
		List<Apple> result = filter(inventory, new AppleHeavyWeightPredicate());
		List<Apple> result2 = filter(inventory, new AppleGreenColorPredicate());
		System.out.println(result.toString());
		System.out.println(result2.toString());
	}
}

 

인터페이스와 구상클래스를 만들어 filter와 클라이언트인 main 메서드 로직자차는 깔끔해지면서 기능을 추가 할 수 있게 되었지만. 기능에 늘어남에 따라 클래스또한 추가될 것이다.

익명클래스, 람다로 구현

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

 

익명클래스, 람다로 구현하면 이전에 사용하던 ApplePredicate 구현 클래스들은 없어도 된다.

public class TestCase06 {
	public static final Color GREEN = Color.GREEN;
	public static final Color RED = Color.RED;
	public static final Color BLUE = Color.BLUE;
	public static final Color YELLOW = Color.YELLOW;
	public static final Color WHITE = Color.WHITE;
	public static final Color BLACK = Color.BLACK;
	
	public static List<Apple> filter(List<Apple> inventory, ApplePredicate p){
		List<Apple> result = new ArrayList<Apple>();
		for(Apple apple: inventory) {
			if(p.test(apple)) {
				result.add(apple);
			}
		}
		return result;
	}
	
	public static void main(String[] args) {
		List<Apple> inventory = Arrays.asList(
			 new Apple(Color.GREEN, 10)
			,new Apple(Color.RED, 50)
			,new Apple(Color.BLUE, 100)
			,new Apple(Color.YELLOW, 150)
			,new Apple(Color.WHITE, 200)
			,new Apple(Color.BLACK, 100)
			,new Apple(Color.GREEN, 100)
			,new Apple(Color.GREEN, 150)
		);
		
		//익명 클레스 사용
		/*List<Apple> result = filter(inventory, new ApplePredicate() {
			@Override
			public boolean test(Apple apple) {
				return apple.getWeight() > 150;
			}
		});
		List<Apple> result2 = filter(inventory, new ApplePredicate() {
			@Override
			public boolean test(Apple apple) {
				return GREEN.equals(apple.getColor());
			}
		});*/
		
		//람다식 사용
		List<Apple> result = filter(inventory, (Apple apple) -> apple.getWeight() > 150);
		List<Apple> result2 = filter(inventory, (Apple apple) -> GREEN.equals(apple.getColor()));
		
		System.out.println(result.toString());
		System.out.println(result2.toString());
	}
}

 

익명 클레스를 추가해서 이제는 추가 할때마다 구상클래스는 구현할 필요가 없다. 익명 클래스 보단 람다식이 더 직관 적이고 깔끔하고 필요없는 코드도 제거되었다.  하지만 ApplePredicate 인터페이스에 박혀 있는 Apple클래스로 인하여 Apple 클래스만 test할수 있는 로직이 되었다 이것 또한 개선 할 수 있다.

리스트 형식으로 추상화

public interface Predicate {
	boolean test(T t);
}

 

public class TestCase07 {
	public static final Color GREEN = Color.GREEN;
	public static final Color RED = Color.RED;
	public static final Color BLUE = Color.BLUE;
	public static final Color YELLOW = Color.YELLOW;
	public static final Color WHITE = Color.WHITE;
	public static final Color BLACK = Color.BLACK;
	
	public static <T> List<T> filter(List<T> list, Predicate<T> p){
		List<T> result = new ArrayList<T>();
		for(T e: list) {
			if(p.test(e)) {
				result.add(e);
			}
		}
		return result;
	}
	
	public static void main(String[] args) {
		List<Apple> inventory = Arrays.asList(
			 new Apple(Color.GREEN, 10)
			,new Apple(Color.RED, 50)
			,new Apple(Color.BLUE, 100)
			,new Apple(Color.YELLOW, 150)
			,new Apple(Color.WHITE, 200)
			,new Apple(Color.BLACK, 100)
			,new Apple(Color.GREEN, 100)
			,new Apple(Color.GREEN, 150)
		);
		List<Integer> numbers = Arrays.asList(
			1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
		);
		
		List<Apple> result = filter(inventory, (Apple apple) -> apple.getWeight() > 150);
		List<Apple> result2 = filter(inventory, (Apple apple) -> GREEN.equals(apple.getColor()));
		
		List<Integer> evenNumbers = filter(numbers, (Integer i) -> i % 2 == 0);
		
		System.out.println(result.toString());
		System.out.println(result2.toString());
		System.out.println(evenNumbers.toString());
	}
}

 

로직이 깔끔하게 개선되었다. Apple의 색을 필터링 할 수도 Apple의 무게를 필터 할수도 있다. 또한 Apple 클래스가 아닌 다른 값을 넣어 다른 필터로직을 적용하여도 사용이 가능하다.

 

출처

Modern Java in Action

https://www.yes24.com/Product/Goods/77125987

 

모던 자바 인 액션 - 예스24

자바 1.0이 나온 이후 18년을 통틀어 가장 큰 변화가 자바 8 이후 이어지고 있다. 자바 8 이후 모던 자바를 이용하면 기존의 자바 코드 모두 그대로 쓸 수 있으며, 새로운 기능과 문법, 디자인 패턴

www.yes24.com

 

반응형