Шаблон для потока запроса-ответа с внутренними классами - PullRequest
5 голосов
/ 08 марта 2012

У меня есть приложение, которое состоит из двух процессов: одного клиентского процесса с (на основе SWT) графического интерфейса пользователя и одного серверного процесса.Клиентский процесс очень легкий, что означает, что многие операции с графическим интерфейсом пользователя должны будут запрашивать серверный процесс или запрашивать его к чему-либо, например, в ответ на нажатие пользователем кнопки или выбор пункта меню.Это означает, что будет много обработчиков событий, которые выглядят так:

// Method invoked e.g. in response to the user choosing a menu item
void execute(Event event) {
    // This code is executed on the client, and now we need some info off the server:
    server.execute(new RemoteRequest() {
        public void run() {
            // This code is executed on the server, and we need to update the client 
            // GUI with current progress
            final Result result = doSomeProcessing();
            client.execute(new RemoteRequest() {
                public void run() {
                    // This code is again executed on the client
                    updateUi(result);
                }
            }
        }
    });
}

Однако, поскольку server.execute подразумевает сериализацию (выполняется на удаленном компьютере), этот шаблон невозможенне делая сериализуемый весь класс (поскольку внутренние классы RemoteRequest не являются статическими (просто для ясности: не требуется, чтобы реализация Request могла обращаться к родительскому экземпляру, ради приложения они могли бы быть статическими).).

Конечно, одним из решений является создание отдельных (возможно, статических внутренних) классов для Запроса и Ответа, но это ухудшает читабельность и затрудняет понимание потока выполнения.

IЯ пытался найти какой-либо стандартный шаблон для решения этой проблемы, но я не нашел ничего, что отвечало бы моему беспокойству о читаемости.

Чтобы было ясно, этих операций будет много, и операции часто бывают довольнокоротко. Обратите внимание, что Future объекты здесь не совсем полезны, так как во многих случаяходин запрос к серверу должен будет выполнить несколько действий на клиенте (часто меняющихся), и это также не всегда является возвращаемым результатом.

В идеале я хотел бы иметь возможность написать код, подобный этому:(очевидный псевдокод сейчас, пожалуйста, не обращайте внимания на очевидные ошибки в деталях)

String personName = nameField.getText();
async exec on server {
    String personAddress = database.find(personName);
    async exec on client {
        addressField.setText(personAddress);
    }
    Order[] orders = database.searchOrderHistory(personName);
    async exec on client {
        orderListViewer.setInput(orders);
    }
}

Теперь я хочу пояснить, что базовая архитектура работает и работает хорошо, причина этого решения в том,Конечно, не приведенный выше пример.Единственное, что я ищу, - это способ написания кода, подобного приведенному выше, без необходимости определять статические классы для каждого перехода процесса.Я надеюсь, что я не просто усложнил ситуацию, приведя этот пример ...

Ответы [ 4 ]

1 голос
/ 25 марта 2012

Я предпочитаю использовать Шаблон команды и универсальные AsynchronousCallbacks. Такой подход используется, например, в GWT для связи с сервером. Команды являются Сериализуемыми, AsyncCallback является интерфейсом.

Что-то в этом роде:

    // from the client
    server.execute(new GetResultCommand(args), new AsyncCallback<Result>() 
            {
                public void onSuccess(Result result) {
                    updateUi(); // happens on the client
                }
            });

Затем серверу необходимо получить команду, обработать ее и выдать соответствующий ответ с результатом.

0 голосов
/ 31 июля 2012

Я на самом деле решил эту проблему, создав базовый класс с настраиваемым сериализатором, который позаботится об этом. Я все еще надеюсь, что это в конечном итоге решится на языке.

0 голосов
/ 27 марта 2012

ПЕРВОЕ: Без Pattern, если бы я предложил, вы можете создать отдельный класс для обработки всех Patterns. Просто передайте экземпляр каждого сгенерированного события Object в класс и делегируйте запрос на событие другим классам. Делегирование приведет к более четкому подходу, просто необходимо использовать instanceof, а затем делегировать дальше. Каждое событие может быть кратким в отдельном месте. Наряду с вышеприведенным подходом, да, COMMAND PATTERN - определенно хороший вариант для регистрации запросов, но вы получаете состояние EVENT для каждого вызванного запроса, поэтому вы можете попробовать STATE PATTERN, поскольку он позволяет объекту изменять свое поведение при изменении состояния.

0 голосов
/ 27 марта 2012

Я столкнулся с подобной проблемой на днях.Существует решение, которое использует анонимные классы (и, следовательно, не требует, чтобы вы определяли статические внутренние классы), но делает эти анонимные классы статичными (и, следовательно, не ссылаются на внешний объект).

Просто определитеанонимные классы в статическом методе, например:

void execute(Event event) {
    static_execute(server, client, event);
}

// An anonymous class is static if it is defined in a static method. Let's use that.
static void static_execute(final TheServer server, final TheClient client, final Event event) {
    server.execute(new RemoteRequest() {
        public void run() {
            final Result result = doSomeProcessing();
            // See note below!
            client.execute(new RemoteRequest() {
                public void run() {
                    updateUi(result);
                }
            });
        }
    });
}

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

- Если подумать, тот же трюк, вероятно, нужно применить еще раз, для направления сервер-> клиент.Я оставлю это в качестве упражнения для читателя: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...