Как создать класс-оболочку вокруг перечисления с динамическим полем - PullRequest
0 голосов
/ 14 марта 2019

В настоящее время я работаю над проектом Android, где я использую перечисление для динамического создания URL.

В зависимости от того, какой RequestOperation выбран и передан моему методу startRequest(), будет вызван другой APIпоэтому для отображения мой старый подход заключался в том, чтобы отобразить значения перечисления с помощью регистра переключателя и вернуть соответствующую часть URL-адреса в виде строки следующим образом:

public enum RequestOperation {

    WORKERS,
    ERRORS_COMPACT,
    ERRORS_COMPLEX,
    ERROR_TAKE_OVER,
    SESSION_CHECK,
    SESSION_LOGIN,
    SESSION_LOGOUT;

    public String parsingKey() {
        switch (this) {
            case WORKERS:
                return "workers";
            case ERRORS_COMPACT:
                return "errors";
            case ERRORS_COMPLEX:
                return "errors";
            case ERROR_TAKE_OVER:
                return "take_over";
            default:
                return "";
        }
    }

    public String apiURL(ArrayList<String> params) {
        switch (this) {
            case WORKERS:
                return "schedule.m";
            case ERRORS_COMPACT:
                return "errors.m?mode=compact";
            case ERRORS_COMPLEX:
                return "errors.m?mode=complex";
            case ERROR_TAKE_OVER:
                return "assign_task.m?param0=" + params.get(0) + "&param1=" + params.get(1);
            case SESSION_CHECK:
                return "desk.m?do=check&param0=" + params.get(0);
            case SESSION_LOGIN:
                return "desk.m?do=login&param0=" + params.get(0) + "&param1=" + params.get(1) + "&param2=" + params.get(2);
            case SESSION_LOGOUT:
                return "desk.m?do=logout&param0=" + params.get(0);
            default:
                return "";
        }
    }

}

Как видите, составление URL-адресаСтроки очень грубые, и я не уверен в этом.Чтобы найти метод для создания тех, которые я пытался создать класс-оболочку для перечисления:

public class RequestOperation {

    public enum Type {
        WORKERS("workers", "workers.m"),
        ERRORS_COMPACT("errors", "errors.m?mode=compact"),
        ERRORS_COMPLEX("errors", "errors.m?mode=complex"),

        //here's where im stuck, cause the second string is not the complete url
        ERROR_TAKE_OVER("take_over", "assign_task.m?param0="),
        SESSION_CHECK("", "desk.m?do=check&dparam0="),
        SESSION_LOGIN("", "desk.m?do=login&param0="),
        SESSION_LOGOUT("", "desk.m?do=logout&param0=");

        //maybe pass the params in here some how, and compose the url selectively
        Type(String parsingKey, String applicationUrl) {
            this.parsing_key = parsingKey;
            this.application_url = applicationUrl;
        }

        //maybe move them out of the enum
        private String parsing_key;
        private String application_url;
        //private ArrayList<String> url_params = new ArrayList<>();
    }

    private Type type;

    //expect parameters from the creator here maybe
    public RequestOperation(Type type) {
        this.type = type;
    }

    public String parsingKey() {
        return type.parsing_key;
    }

    public String application_url() {
        return type.application_url;
    }
}

Теперь моя проблема в том, что я понятия не имею, как передать туда параметры в объекте RequestOperation, так что application_url составляется правильно.Моя первая мысль - перегрузить конструктор Type, чтобы я мог передать еще 3 строки, которые будут заполнены в промежутках, как в первом экспонате.Есть ли способ сделать это, кроме того, это хорошая практика?

Ответы [ 2 ]

2 голосов
/ 14 марта 2019

Я бы не использовал параметры типа ?param0= в объявлении перечисления, но вместо этого оставил бы необработанные URL в вашем перечислении.

Например, эта константа перечисления:

 ERROR_TAKE_OVER("take_over", "assign_task.m?param0=")

изменится на:

ERROR_TAKE_OVER("take_over", "assign_task.m")

и ваш apiURL(String...) может выглядеть так:

public String apiURL(String... params) {
    if(params.length == 0) return type.application_url;
    return type.application_url 
        + "?" 
        + IntStream.range(0, params.length)
                   .mapToObj(i -> String.format("param%d=%s", i, params[i]))
                   .collect(Collectors.joining("&"));

}

и позволить веб-сервлету обрабатывать возможное отсутствие параметра.

Пример:

RequestOperation request = new RequestOperation(RequestOperation.Type.ERROR_TAKE_OVER);
System.out.println(request.apiURL()); //"assign_task.m"
System.out.println(request.apiURL("a")); //"assign_task.m?param0=a"
System.out.println(request.apiURL("a", "b", "c")); //"assign_task.m?param0=a&param1=b&param2=c"
0 голосов
/ 14 марта 2019

Возможно, это не лучшее решение, а просто обходной путь.В идеале enum должен хранить постоянные значения, а не динамические.В вашем случае, обходной путь должен был бы использовать MessageFormat#format().Значение application_url в enum будет содержать строку с заполнителями в виде:

SESSION_LOGIN("", "desk.m?do=login&param0={0}&param1={1}")

Обратите внимание на использование {} в качестве заполнителя.

Теперь создайте метод, который будет формировать URLоснованный на переданных параметрах как:

public String getApiUrl(String... params) {
    return MessageFormat.format(this.application_url, params);
}

Остерегайтесь, что это очень грубый способ сделать то, что вы пытаетесь достичь, так как он не проверяет, какие или сколько параметров можно было передать.

...