if 없이 런타임에 동적으로 행동한 척 하기

minseok·2023년 5월 4일
0
post-thumbnail

🐿️ abstract class, static 혼합

추상클래스 Result와 이를 상속하는 RedResult, BlueResult, GreenResult가 존재합니다.
각각의 정확한 구현체에 따라 다른 행동을 하기를 원합니다.

Result라는 이름은 무시해주세요..





abstract class에 protected 접근 제한자를 사용해서 나를 상속한 객체에서만 map에 접근하게 사용합니다.
static block에서 분기처리를 해서 if가 사용되지 않도록 합니다.

map의 접근 제한자가 같은 패키지도 허용하니 Result class의 위치를 잘 설정해야함

public abstract class Result {
	
    // 값을 미리 매칭합니다. 다른 자료구조, 알고리즘도 가능
    protected static Map<Class, Integer> map = new HashMap<>();
    // 얘를 사용해서 map에 접근해야함
    abstract public Integer getValue();
    // 셋업
    static {
        map.put(RedResult.class, 1);
        map.put(BlueResult.class, 2);
        map.put(GreenResult.class, 3);
    }
}

Result를 상속받은 다양한 형태의 Result들은 모두 getValue를 재정의합니다.
this.getClass()가 아니라 구현체의 종류를 구별하는 것이면 무엇이라도 가능

getValue()를 통해서만 map에 접근하는 것이 중요합니다.

public class BlueResult extends Result{

    @Override
    protected Integer getValue() {
        return map.get(this.getClass());
    }
}
public class GreenResult extends Result{

    @Override
    protected Integer getValue() {
        return map.get(this.getClass());
    }
}
public class RedResult extends Result{

    @Override
    protected Integer getValue() {
        return map.get(this.getClass());
    }
}

abstract getValue()를 활용하면 런타임에 최소한의 정보로 정확한 정보와 결합된 정보를 동적으로 얻을 수 있습니다.

BlueResult blueResult = new BlueResult();
GreenResult greenResult = new GreenResult();
RedResult redResult = new RedResult();

Result result = null;

result = blueResult;
System.out.println(result.getValue());
result = greenResult;
System.out.println(result.getValue());
result = redResult;
System.out.println(result.getValue());




🐇 Enum

public enum CalculatorType {

    CALC_A(value -> value),
    CAL_B(value -> value * 10),
    CAL_C(value -> value * 3),
    CAL_ETC(value -> 0l);

    private Function<Long, Long> expressions;

    CalculatorType(Function<Long, Long> expressions) { this.expressions = expressions; }

    public long calculate(long value) { return expressions.apply(value); }
}

어떤 값을 반환하는지 판단할 수 있는가?

public class Main {
    public static void main(String[] args) {
        CalculatorType calculatorType = ???;
        calculatorType.calculate(10);
    }
}

CalculatorType과 연관된 행위에 대하여 다른 곳에 물어보지 않습니다.

참조 : https://techblog.woowahan.com/2527/




🐰 Inject

Bean주입을 통하여 분기 처리를 하였습니다.
DI Framework를 사용하는 환경이라면 사용가능한 기법입니다.

@Component
public class Guard {
    @AutoWired
    private List<PassCondition> passConditions;

    // "올바른 요청인가?"에 대하여 True/False를 알려줘
    // True/ False를 가르는 조건이 여러가지 존재한다.
    // 1개만 통과하면 Pass
    public boolean isPass(String request) {
        return passConditions.stream()
                .anyMatch(passCondition -> passCondition.isPass(request));
    }
}

이 인터페이스를 사용해서 Bean에 등록하면 위에 passConditions에 등록됩니다.

@FunctionalInterface
public interface PassCondition {
    boolean isPass(String request);
}

PassCondition의 구현체 리스트입니다.
@Component로 모두 Bean으로 등록합니다.

@Component
public class PassCondition1 implements PassCondition{
    @Override
    public boolean isPass(String request) {
        return request.length() > 6;
    }
}
@Component
public class PassCondition2 implements  PassCondition{
    @Override
    public boolean isPass(String request) {
        return request.isEmpty();
    }
}
@Component
public class PassCondition3 implements PassCondition {
    @Override
    public boolean isPass(String request) {
        return request.equals("PASS");
    }
}
profile
즐겁게 개발하기

0개의 댓글