on
if문
확인방법: 바이트코드
if(a && b && c && d && e && f && g)
if(a)
if(b)
if(c)
if(d)
if(e)
if(f)
if(g)
:둘다 동일한 바이트코드로 컴파일됨.
boolean a=true, b=true, c=true, d=true, e=true, f=true, g=true;
0: iconst_1
1: istore_1
2: iconst_1
3: istore_2
4: iconst_1
5: istore_3
6: iconst_1
7: istore 4
9: iconst_1
10: istore 5
12: iconst_1
13: istore 6
15: iconst_1
16: istore 7
if(a && b && c && d && e && f && g) {}
18: iload_1
19: ifeq 45
22: iload_2
23: ifeq 45
26: iload_3
27: ifeq 45
30: iload 4
32: ifeq 45
35: iload 5
37: ifeq 45
40: iload 6
42: ifeq 45
if(a) if(b) if(c) if(d) if(e) if(f) if(g) {}
45: iload_1
46: ifeq 72
49: iload_2
50: ifeq 72
53: iload_3
54: ifeq 72
57: iload 4
59: ifeq 72
62: iload 5
64: ifeq 72
67: iload 6
69: ifeq 72
최적화
1.스위치문
public int calculate(int a, int b, String operator) {
int result = Integer.MIN_VALUE;
if ("add".equals(operator)) {
result = a + b;
} else if ("multiply".equals(operator)) {
result = a * b;
} else if ("divide".equals(operator)) {
result = a / b;
} else if ("subtract".equals(operator)) {
result = a - b;
}
return result;
}
public int calculateUsingSwitch(int a, int b, String operator) {
switch (operator) {
case "add":
result = a + b;
break;
// other cases
}
return result;
}
장점 : 간단, 유지보수용이 단점 : 복잡한논리엔 부적합
리팩토링
3.1 팩토링클래스 ::원하는 타입 객체를 반환
연산 인터페이스
public interface Operation {
int apply(int a, int b);
}
구현
public class Addition implements Operation {
@Override
public int apply(int a, int b) {
return a + b;
}
}
구현클래스들의 hashmap소유 클래스 //map으로 두면 더빠름
public class OperatorFactory {
static Map<String, Operation> operationMap = new HashMap<>();
static {
operationMap.put("add", new Addition());
operationMap.put("divide", new Division());
// more operators
}
public static Optional<Operation> getOperation(String operator) {
return Optional.ofNullable(operationMap.get(operator));
}
숫자, 연산자를 받아 , 팩터링클래스에 넘긴후 객체를 return받기
public int calculateUsingFactory(int a, int b, String operator) {
Operation targetOperation = OperatorFactory
.getOperation(operator)
.orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
return targetOperation.apply(a, b);
}
3.2 Enums
logic에 enum 부여 ,if , switch , factor의 조건으로 사용
- 연산 label 지정
public enum Operator { ADD, MULTIPLY, SUBTRACT, DIVIDE } - 구현
ADD {
@Override
public int apply(int a, int b) {
return a + b;
}
},
// other operators
public abstract int apply(int a, int b);
3.라우터
public int calculate(int a, int b, Operator operator) {
return operator.apply(a, b);
}
Operator#valueOf() method 로 String 을 operator로 변환해서 사용
@Test
public void whenCalculateUsingEnumOperator_thenReturnCorrectResult() {
Calculator calculator = new Calculator();
int result = calculator.calculate(3, 4, Operator.valueOf("ADD"));
assertEquals(7, result);
}
3.3명령패턴
명령을받는 Calculator#calculate which can be executed on the inputs. //중첩 if 개선
1.커맨드
public interface Command {
Integer execute();
}
2.add커맨드
public class AddCommand implements Command {
// Instance variables
public AddCommand(int a, int b) {
this.a = a;
this.b = b;
}
@Override
public Integer execute() {
return a + b;
}
}
3.command를 받는 method
public int calculate(Command command) {
return command.execute();
}
4.AddCommand객체생성, Calculator#calculate method에 보내기:
@Test
public void whenCalculateUsingCommand_thenReturnCorrectResult() {
Calculator calculator = new Calculator();
int result = calculator.calculate(new AddCommand(3, 7));
assertEquals(10, result);
}
3.4룰엔진
중첩 if문 평가 규칙 규칙과 입력에따라 반환 복잡성제거
1.rule
public interface Rule {
boolean evaluate(Expression expression);
Result getResult();
}
2.rule engine
public class RuleEngine {
private static List<Rule> rules = new ArrayList<>();
static {
rules.add(new AddRule());
}
public Result process(Expression expression) {
Rule rule = rules
.stream()
.filter(r -> r.evaluate(expression))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule"));
return rule.getResult();
}
}
RuleEngine은 Expression object를받아 결과반환 Expression:
public class Expression {
private Integer x;
private Integer y;
private Operator operator;
} //두 정수와 연산의 expression
addrule
public class AddRule implements Rule {
@Override
public boolean evaluate(Expression expression) {
boolean evalResult = false;
if (expression.getOperator() == Operator.ADD) {
this.result = expression.getX() + expression.getY();
evalResult = true;
}
return evalResult;
}
}
호출: engin.process(expression)
@Test
public void whenNumbersGivenToRuleEngine_thenReturnCorrectResult() {
Expression expression = new Expression(5, 5, Operator.ADD);
RuleEngine engine = new RuleEngine();
Result result = engine.process(expression);
assertNotNull(result);
assertEquals(10, result.getValue());
}
assert문:: //jdk1.4 이상
assert expression1; //참:pass 거짓:AssertionError
assert expression1: expression2; //exp1참 : pass 거짓 : exp2출력
출처::
https://www.baeldung.com/java-replace-if-statements