Как моделировать классы, обрабатывающие сообщения proto3? - PullRequest
0 голосов
/ 10 июля 2020

У меня есть следующие сообщения proto3:

message Condition {
    oneof value {
        bool booleanLiteral = 1; /** True/False */
        BinaryCondition binaryCondition = 2;
        UnaryCondition unaryCondition = 3;
    }
}

message BinaryCondition {
    enum Operator {
        AND = 0; /** Boolean AND */
        OR = 1; /** Boolean OR */
    }
    Operator operator = 1; /** A valid operator that joins 2 conditions */
    Condition firstOperand = 2; /** The first condition */
    Condition secondOperand = 3; /** The second condition */
}

message UnaryCondition {
    enum Operator {
        NOT = 0; /** Boolean NOT */
    }
    Operator operator = 1; /** A valid operator that modifies the value of 1 condition */
    Condition operand = 2;/** The condition subject to modification */
}

Вопрос

Учитывая объект Java 11 Condition, я должен оценить базовое логическое выражение . Как мне разработать классы и интерфейсы для оценки? У меня есть 2 идеи. Может ли кто-нибудь подсказать мне лучший подход или проверить мои подходы?

Мои подходы

Я придумал 2 способа моделирования класса Evaluator:

  1. Несколько перегруженных функций evaluate с разными типами и подтипами Condition в качестве параметра в одном классе.
  2. Несколько классов, переопределяющих реализацию по умолчанию evaluate в общем c базовый класс. Это решение представляет собой сочетание стратегии и фабричного шаблона.

Фрагмент, соответствующий второму подходу:

class Evaluator<T> {

    protected T condition;

    protected Evaluator(final T condition) {
        this.condition = condition;
    }

    public static Evaluator<?> newInstance(final Object condition) {
        if (condition instanceof Condition) {
            return new ConditionEvaluator((Condition) condition);
        } else if (condition instanceof BinaryCondition) {
            return new BinaryConditionEvaluator((BinaryCondition) condition);
        } else if (condition instanceof UnaryCondition) {
            return new UnaryConditionEvaluator((UnaryCondition) condition);
        } else {
            return new Evaluator<Boolean> (false);
        }
    }

    public boolean evaluate() {
        return false;
    }
}

class ConditionEvaluator extends Evaluator<Condition> {
    public ConditionEvaluator(final Condition condition) {
        super(condition);
    }

    @Override
    public boolean evaluate() {
        // Switch case code can be replaced by using field descriptors instead.
        if (condition.hasBinaryCondition()) {
            return Evaluator.newInstance(condition.getBinaryCondition()).evaluate();
        } else if (condition.hasUnaryCondition()) {
            return Evaluator.newInstance(condition.getUnaryCondition()).evaluate();
        } else {
            return condition.getBooleanLiteral();
        }
    }
}

class BinaryConditionEvaluator extends Evaluator<BinaryCondition> {
    public BinaryConditionEvaluator(final BinaryCondition condition) {
        super(condition);
    }

    @Override
    public boolean evaluate() {
        final Evaluator<?> firstEvaluator = Evaluator.newInstance(condition.getFirstOperand());
        final Evaluator<?> secondEvaluator = Evaluator.newInstance(condition.getSecondOperand());

        switch (condition.getOperatorValue()) {
            case BinaryCondition.Operator.AND_VALUE:
                return firstEvaluator.evaluate() && secondEvaluator.evaluate();
            case BinaryCondition.Operator.OR_VALUE:
                return firstEvaluator.evaluate() || secondEvaluator.evaluate();
            default:
                return false;
        }
    }
}

...