Enum은 단순히 데이터의 타입을 정의할 때 사용한다고 생각하기 쉽지만 간단한 문법으로 강력한 다형성을 제공해줍니다.
public enum CalculateType {
ADD, MINUS, MULTIPLY, DIVIDE
}
public class CalculateCommand {
private CalculateType calculateType;
private int num1;
private int num2;
public CalculateCommand(CalculateType calculateType, int num1, int num2) {
this.calculateType = calculateType;
this.num1 = num1;
this.num2 = num2;
}
public CalculateType getCalculateType() {
return calculateType;
}
public int getNum1() {
return num1;
}
public int getNum2() {
return num2;
}
}
public class Client {
public int someMethod(CalculateCommand calculateCommand) {
CalculateType calculateType = calculateCommand.getCalculateType();
int num1 = calculateCommand.getNum1();
int num2 = calculateCommand.getNum2();
int result = 0;
if (calculateType.equals(CalculateType.ADD)) {
result = num1 + num2;
} else if (calculateType.equals(CalculateType.MINUS)) {
result = num1 - num2;
} else if (calculateType.equals(CalculateType.MULTIPLY)){
result = num1 * num2;
} else if (calculateType.equals(CalculateType.DIVIDE)) {
result = num1 / num2;
}
return result;
}
}
간단한 계산기 프로그램입니다. 이 코드에서 눈여겨 보야할 점은 CalculateType으로 인해 분기가 되고 있다. enum을 어떻게 사용하는지를 보시면 됩니다.
public class EnumMain {
public static void main(String[] args) {
CalculateCommand calculateCommand = new CalculateCommand(
CalculateType.ADD,
100,
3
);
Client client = new Client();
int result = client.someMethod(calculateCommand);
System.out.println(result); // 103
}
}
위의 클래스들을 사용하여 덧셈을 해보는 예제 코드입니다. 정상적으로 잘 동작하는 것을 확인할 수 있습니다. 하지만 이 코드를 리펙토링하여 좀 더 객체 지향적으로 바꿔보도록 하겠습니다.
public enum CalculateType {
ADD((num1, num2) -> num1 + num2),
MINUS((num1, num2) -> num1 - num2),
MULTIPLY((num1, num2) -> num1 * num2),
DIVIDE((num1, num2) -> num1 / num2),
private BiFunction<Integer, Integer, Integer> expression;
CalculateType(BiFunction<Integer, Integer, Integer> expression) {
this.expression = expression;
}
public int calculate(int num1, int num2) {
return this.expression.apply(num1, num2);
}
}
enum 클래스에 코드가 복잡해진 것을 볼 수 있습니다. 단순히 타입만 지정한 것이 아니라 타입 + 연산까지 포함하여 정의를 하였습니다.
enum에 생성자가 있습니다. 각각의 타입에 대해서 괄호 부분 안에 부분을 정의한 것입니다.
BiFunction이라는 함수형 인터페이스를 선언하고 생성자에 들어온 Bifunction으로 초기화 하는 것을 확인할 수 있습니다.
enum 타입들은 하나하나가 클래스의 인스턴스와 마찬가지로 필드를 가지고 있다고 생각하면 이해가 편합니다. 생성자도 있고, 필드도 있기 때문입니다.
이제 실제로 사용을 해보도록 하겠습니다.
public class Client {
public int someMethod(CalculateCommand calculateCommand) {
CalculateType calculateType = calculateCommand.getCalculateType();
int num1 = calculateCommand.getNum1();
int num2 = calculateCommand.getNum2();
int result = calculateType.calculate(num1, num2);
return result;
}
}
기존에 if-else if 로 지저분했던 코드가 깔끔하게 바뀐 것을 확인할 수 있습니다. 깔끔하게 바뀐 것 뿐만 아니라 더 객체지향적으로 바뀐 코드입니다.
public class Client {
public int someMethod(CalculateCommand calculateCommand) {
CalculateType calculateType = calculateCommand.getCalculateType();
int num1 = calculateCommand.getNum1();
int num2 = calculateCommand.getNum2();
int result = 0;
if (calculateType.equals(CalculateType.ADD)) {
result = num1 + num2;
} else if (calculateType.equals(CalculateType.MINUS)) {
result = num1 - num2;
} else if (calculateType.equals(CalculateType.MULTIPLY)){
result = num1 * num2;
} else if (calculateType.equals(CalculateType.DIVIDE)) {
result = num1 / num2;
}
return result;
}
}
기존 Client 코드에는 CalculateType에 대해 알아야했고, if-elseif를 사용하여 연산까지 수행하였습니다.
public class Client {
public int someMethod(CalculateCommand calculateCommand) {
CalculateType calculateType = calculateCommand.getCalculateType();
int num1 = calculateCommand.getNum1();
int num2 = calculateCommand.getNum2();
int result = calculateType.calculate(num1, num2);
return result;
}
}
바뀐 코드에서의 Client 코드는 CalculateType에 타입들에 대해서 알 필요가 없고 CalculateType의 존재만 알면 되었습니다. 이렇게 CalculateType은 추상적인 존재가 된 것입니다.
해당 게시글은 프로그래머스 스쿨 강의
"실무 자바 개발을 위한 OOP와 핵심 디자인 패턴(푸)"
를 정리한 내용입니다. 쉽게 잘 설명해주시니 여러분도 강의를 듣는 것을 추천드립니다.
정보 감사합니다.