java对象间通信 [英] java inter object communication

查看:71
本文介绍了java对象间通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

仍在学习Java。



再次,Swing已经让我问这个问题,但这真的是一个一般的OO问题。如果我有一个master类(包含main()),它会创建一个新的对象A,这样就可以做一些事情了,主类现在有一个对该对象的引用,对象B如何访问该对象的属性?



我想到的唯一方法是为主类创建一个新对象B,将对象A作为参数传递给构造函数,其中我想是的但是这不会使事件处理潜在困难。



例如,也许这是一个糟糕的设计,导致问题。我有一个具有程序逻辑的主类,创建一个标准的Swing框架,带有一个菜单,菜单项有动作监听器。但是actionlistener需要与外部对象进行交互。



所以一些代码(忽略细节):



主类,包含程序逻辑和保存和加载方法等:

  public final class TheProgramme实现WindowListener} 
private static final TheProgramme TP = new TheProgramme();
//声明类变量,实例变量等

public static void main(String [] args){
javax.swing.SwingUtilities.invokeLater(new Runnable()
public void run(){
createAndShewGUI();
}
});
}

private static void createAndShewGUI(){
TP.populateAndShew();
}

private void populateAndShew(){
final StandardFrame sF = new StandardFrame(TheProgramme);
theFrame = sF.getMainFrame();
theFrame.addWindowListener(this);
theFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
theFrame.pack(); theFrame.setVisible(真);
}
...
}

所以我们创建了一个标准的框架对象,它已经创建了一个菜单,空面板和状态栏,但在菜单项上有事件监听器:

  public class StandardFrame {
//声明必须对ActionListener内部类可见的实例变量

public StandardFrame(String theTitle){
mainFrame = new的JFrame(theTitle);
mainFrame.setJMenuBar(createMenuBar()); // ...菜单栏和...
mainFrame.setContentPane(createBlankPanel()); // ...一个空白面板
java.net.URL imageURL = TheProgramme.class.getResource(images / icon.png);
if(imageURL!= null){
ImageIcon icon = new ImageIcon(imageURL);
mainFrame.setIconImage(icon.getImage());
}
}

public JMenuBar createMenuBar(){
ActionListener menuEvents = new MenuListener();
JMenuBar aMenuBar = new JMenuBar();
JMenu fileMenu = new JMenu(File); fileMenu.setMnemonic(KeyEvent.VK_F);
...
aMenuBar.add(fileMenu);
...
JMenuItem newItem = new JMenuItem(New,KeyEvent.VK_N); newItem.addActionListener(menuEvents);
newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,ActionEvent.CTRL_MASK));
...
fileMenu.add(newItem);
...
return aMenuBar;
}
}

class MenuListener实现ActionListener {

public void actionPerformed(ActionEvent ae){
String actionCommand = ae.getActionCommand );
switch(actionCommand){
caseNew:
// !!!这里我们需要在对象中调用一个方法来创建一个新的文档对象!
break;
caseReformat:
// !!!这里我们需要在上面创建的对象中调用一个方法
}
}
}

第一个问题是菜单项上的actionlistener调用创建对象的方法,但不是调用静态方法。
第二个问题是由于另一个菜单选择,需要能够在该新对象中调用方法。

解决方案

Model-View-Controller 是在运行时将对象绑定在一起的。控制器,您的动作侦听器,需要参数来指示要执行哪个视图和模型。



这种使用参数也称为依赖注入,作为Aqua提到

  public static void main(String [] args)
{
模型模型=新模型();
View view = new View();
ActionListener listener = new MyActionListener(model,view);
view.addActionListener(listener);
}

私有静态类MyActionListener实现ActionListener
{
私人模型模型;
私人查看视图;

public MyActionListener(Model model,View view)
{
this.model = model;
this.view = view;
}
}

在Java中,您可以欺骗一点,因为ActionEvent具有指向事件源的指针(通常是生成事件的视图/ JComponent。

  private static class MyActionListener implements ActionListener 
{
私人模型模型;

public MyActionListener(模型模型)
{
this.model = model;
}

@Override
public void actionPerformed(ActionEvent e)
{
JComponent source =(JComponent)e.getSource();
// source ==view ...
}
}

要设置新文档,您可以创建一个文件夹类,新建菜单项将新文档放在保持器类中,所有其他菜单项从持有人类获取文档,这是一个相当严格的OO范例,不使用静态方法或田野,虽然有点乏味。



设置:

  public static void main(String [] args)
{
ModelDocumentHolder model = new ModelDocumentHolder();
View view = new View();
ActionListener listener = new NewDocument(model);
view.addActionListener(listener);
查看view2 = new View();
view2.addActionListener(new RegularListener(model));
}

新的文档监听器:



私有静态类NewDocument实现ActionListener
{
private ModelDocumentHolder模型;

public NewDocument(ModelDocumentHolder model)
{
this.model = model;
}

@Override
public void actionPerformed(ActionEvent e)
{
model.setDoc(new Document());
}
}

大多数其他菜单项:

 私有静态类RegularListener实现ActionListener 
{
private ModelDocumentHolder模型;

public RegularListener(ModelDocumentHolder model)
{
this.model = model;
}

@Override
public void actionPerformed(ActionEvent e)
{
JComponent source =(JComponent)e.getSource();
文档doc = model.getDoc();
//做东西...
}
}

持有者类:

 私有静态类ModelDocumentHolder 
{
private Document doc;

public Document getDoc()
{
return doc;
}

public void setDoc(Document doc)
{
this.doc = doc;
}

}


Still learning Java.

Again Swing has caused me to ask this but it is really a general OO question. If I have a master class (that contains main()) it creates a new object "A" that does something, the master class now has a reference to that object, how does object "B" get access to the attributes of that object?

The only way I can think of is for the master class to create a new object "B", passing object "A" as a parameter to the constructor, which I suppose is O.K. but doesn't this make event handling potentially difficult.

For example, and perhaps this is a poor design which is causing the problem. I have a master class with the programme logic, that creates a standard Swing frame, with a menu, the menu items having action listeners. But the actionlistener needs to interact with external objects.

So some code (ignoring the details) :

The main class, containing the programme logic and the save and load methods, etc :

public final class TheProgramme implements WindowListener }
    private static final TheProgramme TP = new TheProgramme();
    // Declare Class variables, instance variables etc.

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShewGUI();
            }
        });
    }

    private static void createAndShewGUI() {
        TP.populateAndShew();
    }

    private void populateAndShew() {
        final StandardFrame sF = new StandardFrame("TheProgramme");
        theFrame = sF.getMainFrame();
        theFrame.addWindowListener(this);
        theFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        theFrame.pack(); theFrame.setVisible(true);
    }
...
}

So we have created a standard frame object which has created a menu, empty panel and status bar, but with event listeners on the menu items :

public class StandardFrame {
    // Declare instance variables that must be visible to the ActionListener inner class

    public StandardFrame(String theTitle) {
        mainFrame = new JFrame(theTitle);
        mainFrame.setJMenuBar(createMenuBar()); // ... the menu bar and ...
        mainFrame.setContentPane(createBlankPanel()); // ... a blank panel
        java.net.URL imageURL = TheProgramme.class.getResource("images/icon.png");
        if (imageURL != null) {
            ImageIcon icon = new ImageIcon(imageURL);
            mainFrame.setIconImage(icon.getImage());
        }
    }

    public JMenuBar createMenuBar() {
        ActionListener menuEvents = new MenuListener();
        JMenuBar aMenuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File"); fileMenu.setMnemonic(KeyEvent.VK_F);
        ...
        aMenuBar.add(fileMenu);
        ...
        JMenuItem newItem = new JMenuItem("New", KeyEvent.VK_N); newItem.addActionListener(menuEvents);
        newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
        ...
        fileMenu.add(newItem);
        ...
        return aMenuBar;
    }
}

class MenuListener implements ActionListener {

    public void actionPerformed(ActionEvent ae) {
        String actionCommand = ae.getActionCommand();
        switch (actionCommand) {
            case "New":
                // !!! here we need to call a method in an object to create a new document object !!!
                break;
             case "Reformat":
                // !!! here we need to call a method in the object created above
         }
     }
}

The first problem is the actionlistener on the menu items calls a method to create an object but it is not a call to a static method. The second problem is it needs to be be able to call a method in that new object later on as a result of another menu choice.

解决方案

The classic way to do this in Model-View-Controller is to bind the objects together at runtime. The controller, your action listener, takes parameters to indicate which view and model it is to act on.

This use of parameters is also called "Dependency Injection," as Aqua mentions.

   public static void main( String[] args )
   {
      Model model = new Model();
      View view = new View();
      ActionListener listener = new MyActionListener( model, view );
      view.addActionListener( listener );
   }

   private static class MyActionListener implements ActionListener
   {
      private Model model;
      private View view;

      public MyActionListener( Model model, View view )
      {
         this.model = model;
         this.view = view;
      }
   }

In Java you can cheat a little since the ActionEvent has a pointer to the source of the event (normally the view/JComponent that generated the event.

private static class MyActionListener implements ActionListener
{
  private Model model;

  public MyActionListener( Model model )
  {
     this.model = model;
  }

  @Override
  public void actionPerformed( ActionEvent e )
  {
     JComponent source = (JComponent) e.getSource();
     // source == "view"...
  }
}

To set a new document, you can create a "document holder" class. The "new" menu item puts a new document in the holder class. All other menu items "get" the document from the holder class. This is a fairly strict OO paradigm which uses no static methods or fields, although it is a little tedious.

Set up:

   public static void main( String[] args )
   {
      ModelDocumentHolder model = new ModelDocumentHolder();
      View view = new View();
      ActionListener listener = new NewDocument( model );
      view.addActionListener( listener );
      View view2 = new View();
      view2.addActionListener( new RegularListener( model ) );
   }

New document listener:

   private static class NewDocument implements ActionListener
   {
      private ModelDocumentHolder model;

      public NewDocument( ModelDocumentHolder model )
      {
         this.model = model;
      }

      @Override
      public void actionPerformed( ActionEvent e )
      {
         model.setDoc( new Document() );
      }
   }

Most other menu items:

   private static class RegularListener implements ActionListener
   {
      private ModelDocumentHolder model;

      public RegularListener( ModelDocumentHolder model )
      {
         this.model = model;
      }

      @Override
      public void actionPerformed( ActionEvent e )
      {
         JComponent source = (JComponent) e.getSource();
         Document doc = model.getDoc();
         // do stuff...
      }
   }

The holder class:

   private static class ModelDocumentHolder
   {
      private Document doc;

      public Document getDoc()
      {
         return doc;
      }

      public void setDoc( Document doc )
      {
         this.doc = doc;
      }

   }

这篇关于java对象间通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆