我在项目中使用MVC模式。 btnAdd创建新的Customer并将MyJPanel1添加为侦听器。当客户更改其状态时,它将触发事件并调用customerChanged。什么时候MyJPanel1customerChanged称为执行某些操作,

  • 它必须停止收听该客户
  • 其他视图必须开始收听该客户

  • 其他一些视图将具有相同的行为。
    我在MyJPanel1customerChanged方法本身中实现了这两个要求。

    已更新

    我的问题是:
  • 从MVC角度来看这是正确的还是我应该有一些其他实体(控制器?)以某种方式处理它?
  • 当客户触发fireEvent方法时,因此c.removeListener(this);中的MyJPanel1会将其自身从侦听器中删除,因此,导致fireEvent' because侦听器中的in for``循环发生了错误。

  • 我会感谢您的帮助。
    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);
            }
        }
    }
    

    最佳答案

    视图仅显示数据;他们永远不会自己拥有任何功能。

    更改内容(例如添加/删除侦听器)是控制器的目的。它将模型连接到视图,并确保一切正常。使视图尽可能哑。

    关于第二个问题:正如您所注意到的,您不能让听众自杀。有几种解决方案:

  • 从侦听器返回一个布尔值,说“我完成了,请删除我”。循环将是:
    for (Iterator<IListener> iter = listeners.iterator(); iter.hasNext(); ) {
        if (!listener.customerChanged(event)) {
            iter.remove();
        }
    }
    
  • 创建一个永远不会删除的新侦听器。相反,让该侦听器将事件转发给感兴趣的视图。这意味着它将把事件发送到MyJPanel1,直到完成该视图为止。从现在开始,该事件将转到其他视图。

    一个好的解决方案是让新的侦听器侦听两个事件:CustomerEventIAmDoneEvent发布的MyJPanel1

    它有两个侦听器列表。在收到IAmDoneEvent之前,所有CustomerEvent都进入第一个列表。此事件后,所有CustomerEvent进入第二个列表。将MyJPanel1添加到第一个列表,并将所有其他视图添加到第二个列表。

    使用您的控制器来建立此侦听器网络。
  • 10-01 17:44