Как разработать сценарий, в котором один подписчик зависит от другого?

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

Но, следуя принципу шаблона наблюдателя, наблюдатели независимы друг от друга. Между наблюдателями не должно быть никакой связи. В моем случае модули хоть и разные, но зависимые. Успешное завершение выполнения первого модуля важно для выполнения следующего модуля. Кроме того, если модуль x выйдет из строя, все изменения, внесенные модулем 1 в модуль x-1, должны быть отменены. То есть либо все модули должны успешно выполниться, либо мы должны откатиться к предыдущему состоянию. Вы можете представить это как транзакцию. Затем я понял, что был неправ, что шаблон наблюдателя — неправильный способ реализовать это.

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


person Vinoth    schedule 09.08.2012    source источник


Ответы (3)


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

В исходном дизайне модуль X вызывается и вызывается к модулю A, B и C. Но проблема в том, что C зависит от B, и поскольку вы не контролируете порядок (и не хотите) выполнения наблюдателей , у тебя проблемы. Я бы посоветовал вам просто сделать C и наблюдателем B вместо наблюдателя A!

Таким образом, когда A вызывает событие, оно будет распространяться в желаемом порядке. А -> Б -> С.

При этом мне интересно, действительно ли вам нужен этот уровень развязки. По сути, вы описываете здесь стандартный поток информации, и если модули не очень многоразовые, вы можете делать вызовы явно. A напрямую вызывает B, который напрямую вызывает C.

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

person Vitaliy    schedule 09.08.2012
comment
Спасибо .. Это действительно очень помогает !!! Reg Transaction - в основном каждый из модулей будет выполнять некоторые обновления в базе данных.. поэтому необходимо, чтобы все модули завершили обновление, иначе мне придется откатиться, потому что это может оставить мою базу данных в несогласованном состоянии, что может привести к отображению ошибочных значения в моем приложении.. - person Vinoth; 09.08.2012
comment
@ Винот, пожалуйста, посмотри мой другой ответ. - person Vitaliy; 09.08.2012

Про транзакционную часть. На самом деле ваша проблема в том, что вы выполняете последовательность операций обновления в базе данных, и сбой одной из них должен отменить все предыдущие.

Наивным решением было бы просто обернуть исходящий вызов в область транзакции.

начать транзакцию A: обновить событие db Raise B: обновить событие db Raise C: обновить транзакцию завершения db.

Это, вероятно, сработает! Единственная проблема заключается в том, что если у вас есть промежуточные вычисления, которые продлевают продолжительность транзакции. Транзакции должны быть как можно короче, поэтому вам нужно убедиться, что вы не «тратите» время во время транзакции на действия, которые не касаются ресурса транзакции.

Если у вас возникла описанная выше проблема, вы можете собрать все команды обновления в одном месте (список лямбда-выражений, каждое из которых переносит отложенное выполнение в базу данных) и запускать их, как только все изменения накапливаются.

person Vitaliy    schedule 09.08.2012

Вы можете использовать Composite и структуру «получить-выполнить-выпустить» для своего наблюдателя. Не уверен, что я бы назвал это наблюдателем больше - это больше похоже на абстракцию транзакции в сочетании с композитом.

Интерфейс будет примерно таким:

public interface TransIf {
  boolean acquire();
  void execute() throws TransFailed;
  void release();
}
person Anders Johansen    schedule 09.08.2012