単純なプログラムを書換えよう(Java編)−EventListener

ObserverではなくEventListenerを使ったMVCです.Observerの場合,Model(Observable)クラスに持たせていたaddObserver/deleteObserverメソッドは,Modelクラスがjava.util.Observableを継承することで取得していました.EventListenerを使う場合,ModelクラスのaddValueListener/removeValueListenerメソッドとして独自に実装しています.JavaWorld 1999年6月号 p.116~122参照です.

//ValueEvent.java
import java.util.EventObject;

public class ValueEvent extends EventObject{
  public ValueEvent(Model model){
    super(model);
  }
  public int getValue(){
    return ((Model)source).getValue();
  }
}
//end

//ValueEvent.java
import java.util.EventListener;

public interface ValueListener extends EventListener{
  public void valueChanged(ValueEvent valueEvent);
}
//end

//Controller.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.awt.Frame;

public class Controller extends WindowAdapter implements ActionListener{
  private Model model;
  
  public Controller(Model model){
    this.model=model;
  }

  public void actionPerformed(ActionEvent actionEvent){
    if(actionEvent.getActionCommand()=="inc"){
      model.inc();
    }
    else{
      model.dec();
    }
  }
  public void windowOpened(WindowEvent windowEvent){
    model.addValueListener((ValueListener)windowEvent.getSource());
    model.setValue(model.getValue());
  }
  public void windowClosing(WindowEvent windowEvent){
    model.removeValueListener((ValueListener)windowEvent.getSource());
    ((Frame)windowEvent.getSource()).dispose();
    if(model.countValueListeners()==0){
      System.exit(0);
    }
  }
}
//end

//Model.java
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;

public class Model{
  private int value;
  private Set listeners=new HashSet();
  
  public Model(){
    this(0);
  }
  public Model(int value){
    setValue(value);
  }

  public final int getValue(){
    return value;
  }
  public final void setValue(int value){
    this.value=value;
    fireValueChanged();
  }

  public int inc(){
    return inc(1);
  }
  public int inc(int value){
    setValue(getValue()+value);
    return getValue();
  }
  public int dec(){
    return dec(1);
  }
  public int dec(int value){
    setValue(getValue()-value);
    return getValue();
  }

  public int countValueListeners(){
    return listeners.size();
  }
  public void addValueListener(ValueListener valueListener){
    if(!listeners.contains(valueListener)){
      listeners.add(valueListener);
    }
  }
  public void removeValueListener(ValueListener valueListener){
    listeners.remove(valueListener);
  }
  public void fireValueChanged(){
    ValueEvent event=new ValueEvent(this);
    for(Iterator i=listeners.iterator();i.hasNext();){
      ((ValueListener)i.next()).valueChanged(event);
      //変化をValueListenerに通知
    }
  }
}
//end

//View.java
import java.awt.*;

public class View extends Frame implements ValueListener{
  private Label value=new Label();

  public View(Controller controller){
    Panel buttons=new Panel();
    Button inc=new Button("inc");
    Button dec=new Button("dec");
    buttons.add(inc);
    buttons.add(dec);
    inc.addActionListener(controller);
    dec.addActionListener(controller);
    add(buttons,BorderLayout.SOUTH);
    add(value,BorderLayout.CENTER);
    addWindowListener(controller);
    pack();
    show();
  }
  public void valueChanged(ValueEvent valueEvent){
    value.setText(Integer.toString(valueEvent.getValue())); 
    //ModelのfireValueChangedを受けてViewのvalueChangedメソッドが動く
  }
}
//end

//Main.java
public class Main{
  public static void main(String[] args){
    new View(new Controller(new Model()));
  }
}
//end