単純なプログラムを書換えよう(Java編)−java.util.Propertiesの使用

引数のあるコンストラクタをCommandに定義のCommandDispatcherクラスで行っている,画面から受け取った文字列と実行するコマンドのひも付けを,プロパティファイルを使ってやってみよう.具体的には,こんなファイル(command.properties)を作るわけだ.

inc=IncCommand
dec=DecCommand
  

このファイルを読んで,ボタンを押した際に実行するコマンドを決める.変更箇所はCommandDispatcher.javaである.

//CommandDispatcher.java
import java.lang.reflect.*;
import java.util.Map;
import java.util.Properties; //プロパティファイルを使うのでインポート
import java.io.*;

public class CommandDispatcher{
  private static Map commands;
  private static CommandDispatcher commandDispatcher=new CommandDispatcher();
  private static Model model;

  static{ //HashMapに設定していた文字列とCommandクラスとの対応を,プロパティファイルからの読込みに変更.
    Properties prop=new Properties();
    try{
      prop.load(new FileInputStream("command.properties"));
    }
    catch(FileNotFoundException e){
      e.printStackTrace();
    }
    catch(IOException e){
      e.printStackTrace();
    }
    commands=(Map)prop; //PropertiesからMapへ変換
  }
  private CommandDispatcher(){
  }
  public static CommandDispatcher getInstance(Model model){
    commandDispatcher.model=model;
    return commandDispatcher;
  }

  public Command getCommand(String command){
    Command executeCommand=null;
    try{
      Class aClass=Class.forName(commands.get(command).toString()); 
      //生成するクラスを取得.インスタンスはまだできていない
      Class[] classArgs={this.model.getClass()}; 
      //コンストラクタに渡す引数で配列作成.引数はインスタンスではなくクラス
      Constructor aCons=aClass.getConstructor(classArgs); 
      //配列に設定した引数を持つコンストラクタを取得
      Object[] objArgs={this.model}; 
      //コンストラクタに渡す引数で配列作成.次行でコンストラクタを動かすのでインスタンス
      executeCommand=(Command)aCons.newInstance(objArgs); 
      //引数を指定してコンストラクタを起動.インスタンスを取得
    }
    catch(ClassNotFoundException e){
      e.printStackTrace();
    }
    catch(NoSuchMethodException e){
      e.printStackTrace();
    }
    catch(InstantiationException e){
      e.printStackTrace();
    }
    catch(IllegalAccessException e){
      e.printStackTrace();
    }
    catch(InvocationTargetException e){
      e.printStackTrace();
    }
    return executeCommand;
  }
}
//end
  

ちなみに,command.propertiesを書換えて,

inc=DecCommand
dec=IncCommand
  

とすると,incボタンで減算,decボタンで加算できる.そんなことをしてどうするのか,ってのは置いといて.

CommandDispatcher.java以外のソースには変更はない.参考に以下に載せとこう.

//Command.java
public interface Command{
  void execute();
}
//end

//IncCommand.java
public class IncCommand implements Command{
  private Model model;

  public IncCommand(Model model){
    this.model=model;
  }
  public void execute(){
    model.inc();
  }
}
//end

//DecCommand.java
public class DecCommand implements Command{
  private Model model;

  public DecCommand(Model model){
    this.model=model;
  }
  public void execute(){
    model.dec();
  }
}
//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;
import java.util.Observer;

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

  public void actionPerformed(ActionEvent actionEvent){
    commandDispatcher.getCommand(actionEvent.getActionCommand()).execute();
  }

  public void windowOpened(WindowEvent windowEvent){
    model.addObserver((Observer)windowEvent.getSource());
    model.setValue(model.getValue());
  }
  public void windowClosing(WindowEvent windowEvent){
    model.deleteObserver((Observer)windowEvent.getSource());
    ((Frame)windowEvent.getSource()).dispose();
    if(model.countObservers()==0){
      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();
  }

  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 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 update(Observable obs,Object obj){
    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