I use MVC pattern for my project. btnAdd creates new Customer and adds MyJPanel1 as a listener. When Customer changes its state it fires event and customerChanged is called. When
MyJPanel1‘s customerChanged is called it does some action and
- it has to stop listening to that Customer
- other view/s has to start listen to that Customer
Some of other views will have the same behavior.
Those 2 requirements I implemented in MyJPanel1‘s customerChanged method itself.
UPADTED
My question and problem are:
- Is this correct from the point of MVC or I should have some other entity(Controller?) that should handle it somehow?
- When Customer fires
fireEventmethod soc.removeListener(this);inMyJPanel1removes itself from listeners and by this cause error infireEvent' becauselistenersinfor` loop was changed.
I’ll appreciate for some help.
class Customer {
// ...
private void fireEvent(CustomerEvent event) {
for (IListener listener : listeners) {
listener.customerChanged(event);
}
}
}
class MyJPanel1 extends JPanel implements IListener {
MyJPanel2 otherPanel;
MyJPanel1(MyJPanel2 panel) {
this.otherPanel = panel;
createGui();
}
private void createGui() {
JButton btnAdd = new JButton("Add");
btnAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Customer c = new Customer();
c.addListener(this);
}
});
// ...
}
@Override
public void customerChanged(CustomerEvent event) {
if (event instanceof AddedCustomerEvent) {
Customer c = event.getCustomer();
// do something
c.removeListener(this);
c.addListener(otherPanel);
}
}
}
Views just display data; they never have any functionality on their own.
Changing things (like adding/removing listeners) is the purpose of the controller. It will hook up the model to the view and make sure that everything works. Make the view as dumb as possible.
Regarding your second problem: As you noticed, you can’t have listeners that commit suicide. There are several solutions:
Return a boolean from the listener saying “I’m done, remove me”. The loop would then be:
Create a new listener that is never removed. Instead let this listener forward the events to the interested views. That means it will send the event to
MyJPanel1until that view is done with it. From now on, the event will go to the other views.A good solution would be to have the new listener listen to two events: The
CustomerEventand theIAmDoneEventpublished byMyJPanel1.It has two lists of listeners. Until
IAmDoneEventis received, allCustomerEventgo to the first list. After this event, allCustomerEventgo to the second list. AddMyJPanel1to the first list and all other views to the second list.Use your controller to build up this listener network.