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

GUIといえば,定番はMVC(Model-View-Controller).ということで,Observerを使ってMVCです.

動く順序はこうです.

  1. Viewを表示する際,ControllerのwindowOpenedメソッドが動く
  2. View(Observer)をModel(Observable)に登録
  3. ボタンを押す
  4. Controller(ActionListener)のactionPerformedメソッドが動く
  5. 押したボタンがincだったらModelのincメソッドを,decだったらModelのdecメソッドを呼ぶ
  6. Modelのincメソッドまたはdecメソッドの中でsetValueメソッドを呼び属性valueの値が変わる
  7. setChanged()とnotifyObserver()を呼ぶとView(Observer)のupdateメソッドが動く
  8. Viewの値が変わる
//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;
import java.util.Observer;

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();
      //押したボタンがincだったら,Modelのincメソッドを呼ぶ
    }
    else{
      model.dec();
      //押したボタンがdecだったら,Modelのdecメソッドを呼ぶ
    }
  }
  public void windowOpened(WindowEvent windowEvent){
    model.addObserver((Observer)windowEvent.getSource());
    //ViewをModelのObserverとして追加
    model.setValue(model.getValue()); 
    //Modelの初期値をViewに送る
  }
  public void windowClosing(WindowEvent windowEvent){
    model.deleteObserver((Observer)windowEvent.getSource());
    //閉じるViewをModelのObserverから削除
    ((Frame)windowEvent.getSource()).dispose();
    if(model.countObservers()==0){
    //Modelに登録していたView(Observer)がなくなったらプログラム終了
      System.exit(0);
    }
  }
}
//end

//Model.java
import java.util.Observable;

public class Model extends Observable{
  private int value;
  
  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;
    setChanged();
    notifyObservers();
    //変化をObserverに通知
  }

  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();
  }
}
//end

//View.java
import java.awt.*;
import java.util.Observer;
import java.util.Observable;

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

  public View(Controller aController){
    Panel buttons=new Panel();
    Button inc=new Button("inc");
    Button dec=new Button("dec");
    buttons.add(inc);
    buttons.add(dec);
    inc.addActionListener(aController);
    dec.addActionListener(aController);
    add(buttons,BorderLayout.SOUTH);
    add(value,BorderLayout.CENTER);
    addWindowListener(aController);
    pack();
    show();
  }
  public void update(Observable obs,Object obj){
  //Model(Observable)のnotifyObserverを受けてView(Observer)のupdateメソッドが動く
    value.setText(Integer.toString(((Model)obs).getValue()));
  }
}
//end

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