В настоящее время я пытаюсь создать библиотеку для передачи сообщений, и один из принципов передачи сообщений заключается в том, что изменяемое состояние изменяется только через сообщения. «Сообщения», которые будут переданы, являются функциональными объектами, которые принимают «отправителя» (который создал сообщение) и «получателя» (рабочий / субъект / что вы обрабатываете сообщение из его очереди.)
Рабочие определяются следующим образом, и самореференциальный характер интерфейса используется, поскольку рабочий может иметь состояние, которое он хочет предоставить отправителям сообщений, и для этого требуется, чтобы отправитель знал о своем уникальном типе.
public interface Worker<T extends Worker<T>> {
T getWorker(); //convert a Worker<T> to it's <T> since T extends Worker<T>
<S extends Worker<S>> void message(Message<S,T> msg);
}
где <S>
- тип работника, который отправил сообщение.
Сообщения определяются следующим образом:
public interface Message<S extends Worker<S>,R extends Worker<R>> {
void process(S sender, R thisWorker);
}
где <S>
- это тип класса отправителя, а <R>
- это тип класса работника обработки. Как и ожидается интерфейсом и механизмом передачи сообщений, функция сможет изменять состояние thisWorker
. Тем не менее, если бы сообщение было непосредственно изменено sender
, возникло бы состояние гонки, потому что синхронизация между рабочими / потоками отсутствует (в этом и заключается весь смысл использования сообщений для начала!)
Хотя я мог бы объявить <S>
родовым Worker<?>
, это лишило бы способность сообщения «отвечать» содержательному ответу отправителю, поскольку оно больше не могло ссылаться на свои конкретные поля.
Следовательно, как я могу гарантировать, что sender
не будет изменен, кроме как в контексте сообщения, адресованного специально ему?
T extends Worker<T>
действительно используется для предотвращения возврата классом неработающего типа. Я мог бы просто сойти с рук Worker<T>
и доверять пользователю.
Чего я конкретно пытаюсь добиться, так это системы передачи сообщений, в которой сообщения являются кодом, что позволило бы избежать необходимости какой-либо специальной обработки различных типов сообщений у каждого работника. Тем не менее, я, вероятно, понимаю, что не существует элегантного способа сделать это без соблюдения какого-либо протокола сообщений, если бы я хотел применить его, например, при выполнении на Swing EDT.