觀察員/事件聽眾
?
public class LocaleChangeEvent extends EventObject {Locale locale;public LocaleChangeEvent(Object source, Locale locale) {super(source);this.locale = locale;}public Locale getLocale() {return locale;}
}
其次,我們需要一個接口LocaleChangeListener。
public interface LocaleChangeListener extends EventListener {void processLocaleChange(LocaleChangeEvent event);
}
@ManagedBean
@SessionScoped
public class UserSettingsForm implements Serializable {private Locale selectedLocale;private List<SelectItem> locales;private List<LocaleChangeListener> localeChangeListeners = new ArrayList<LocaleChangeListener>();public void addLocaleChangeListener(LocaleChangeListener listener) {localeChangeListeners.add(listener);}public void localChangeListener(ValueChangeEvent e) {...// notify listenersLocaleChangeEvent lce = new LocaleChangeEvent(this, this.selectedLocale);for (LocaleChangeListener lcl : localeChangeListeners) {lcl.processLocaleChange(lce);}}...
}
@ManagedBean
@SessionScoped
public MyBean implements LocaleChangeListener, Serializable {// UserSettingsForm can be injected e.g. via @ManagedProperty annotation or via Spring facilityprivate UserSettingsForm userSettingsForm;@PostConstructpublic void initialize() {userSettingsForm.addLocaleChangeListener(this);}public void processLocaleChange(LocaleChangeEvent event) {// reset something related to I18N data...}
}
就觀察者模式而言,UserSettingsForm是可觀察的,而LocaleChangeListener的實例(如MyBean)則是觀察者。 討論的模式帶有一些您需要注意的重要問題。 豆緊密耦合。 有很多手動工作來重新注冊bean。 Bean必須實現定義的接口。 如果您有100個語義不同的更改通知了bean,則它必須實現100個接口。 無法通知已注冊的偵聽器的子集–即使不需要通知所有偵聽器,也總是會通知他們。 最后但并非最不重要的– 內存管理問題 。 馬丁·福勒(Martin Fowler)寫道: “假設我們有一些觀察某些域對象的屏幕。 關閉屏幕后,我們希望將其刪除,但是域對象實際上通過觀察者關系攜帶了對屏幕的引用。 在內存管理的環境中,壽命長的域對象可能會占據很多僵尸屏幕,從而導致大量內存泄漏。”
調解員
?
public interface MediatorEvent {...
}public interface MediatorListener {public void listenToEvent(MediatorEvent event);
}public class Mediator implements Serializable {private Collection<MediatorListener> collaborators = new HashSet<MediatorListener>();public static Mediator getCurrentInstance() {// access Mediator bean by JSF-Spring facilityreturn ContextLoader.getCurrentWebApplicationContext().getBean("mediator");}public void fireEvent(MediatorEvent event) {for (MediatorListener mediatorListener : collaborators) {mediatorListener.listenToEvent(event);}}public void addCollaborator(MediatorListener collaborator) {collaborators.add(collaborator);}public void removeCollaborator(MediatorListener collaborator) {collaborators.remove(collaborator);}
}
public MyBean implements MediatorListener, InitializingBean, Serializable {public void afterPropertiesSet() throws Exception {...Mediator.getCurrentInstance().addCollaborator(this);}@Overridepublic void listenToEvent(MediatorEvent event) {if (event instanceof LocaleChangeEvent) {// do something}}
}
public class LocaleChangeEvent implements MediatorEvent {...
}public class UserSettingsForm implements Serializable {private Locale selectedLocale;private List<SelectItem> locales;public void localChangeListener(ValueChangeEvent e) {...// notify listenersMediator.getCurrentInstance().fireEvent(new LocaleChangeEvent(this, this.selectedLocale));}...
}
參考: JSF中基于事件的通信。 我們的JCG合作伙伴 Oleg Varaksin在“ 軟件開發思想”博客上的過時做法 。
翻譯自: https://www.javacodegeeks.com/2012/07/jsf-event-based-communication-old.html