Java StepUpPrograming〜リファクタリング→クラスを使う〜

イントロダクション

前回、ようやく画面切り替えを実装できました。長かったような短かったような。。。しかし、これで終わりではなく、むしろ始まる感じです (笑)

とりあえず、今回は自分の作業時間の都合があり、リファクタリングのみで終わります。

リファクタリングの内容

今回は、Eclipseで比較します。。。

  1. <プロジェクト・エクスプローラーで右クリック→チーム→ヒストリー>でコミット履歴を表示する
  2. <現在のソースと比較したいリビジョン(コミットした時の番号)を選択して右クリック>
  3. 現在のソースと比較をクリックする

Gitでのソース比較です。

修正後のソース

package jp.zenryoku.fx;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.concurrent.Worker.State;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import jp.zenryoku.fx.pane.JavaBasicPane;
import jp.zenryoku.fx.pane.WebLoaderPane;

/**
 * JavaFXでのハローワールド〜OpenCVなどの
 * 作成したアプリをテストするための、スタンドアロンアプリ。
 * 
 * @author takunoji
 * 2019/01/23
 */
public class RootFxMain2 extends Application {
	/** 画面の縦幅 */
	private static final double VIEW_HEIGHT = 500.0;
	/** 画面の横幅 */
	private static final double VIEW_WIDTH = 500.0;
	/** コントロールボタンのリスト */
	private ArrayList<Button> buttonList;
	/** startメソッドから引っ越ししてフィールド変数にします */
	private BorderPane baseLayout;

	/**
	 * 親クラスのメソッドをオーバーライドする。
	 * 画面を作成したり、ペインを作成したり、色々。。。
	 * 
	 * @see javafx.application.Application#start(javafx.stage.Stage)
	 */
	@Override
	public void start(Stage primaryStage) throws Exception {
		// JavaBasic画面用のコントロールボタンを作成する
		this.cretateControllButtonList();

		// 画面部分とコントロールボタン部分にレイアウト(表示領域を分ける)
		baseLayout = new BorderPane();
		
		// Stageの設定
		primaryStage.setHeight(VIEW_HEIGHT);
		primaryStage.setWidth(VIEW_WIDTH);

		// このクラスにあるメソッドなので名前だけで呼び出せる
		baseLayout.setCenter(JavaBasicPane.getInstance());
		// このクラスのメソッドであることを明示的に示すのに「this」を使用する
		baseLayout.setBottom(this.createFooterPanel());
		// 土台になるレイアウト(ペイン)をステージに追加する
		primaryStage.setScene(new Scene(baseLayout, VIEW_WIDTH, VIEW_HEIGHT));
		primaryStage.show();
	}

	/**
	 * 画面のフッター部分にコントロール用のボタンを配置する。
	 * 
	 * @return Pane レイアウトコンテナ
	 */
	private Pane createFooterPanel() {
		HBox hBox = new HBox(buttonList.size());
		for(Button ctlBtn : buttonList) {
			hBox.getChildren().add(ctlBtn);
		}
		return hBox;
	}

	/**
	 * コントロールボタンを作成する。
	 * 
	 */
	private void cretateControllButtonList() {
		// デザインパターン:シングルトンの実装
		if (buttonList == null) {
			buttonList = new ArrayList<Button>();
		}
		Button viewChangeBtn = new Button("画面切り替え");
		viewChangeBtn.setOnAction(event -> {
			baseLayout.getChildren().remove(0);
			baseLayout.setCenter(WebLoaderPane.getInstance());
		});
		buttonList.add(viewChangeBtn);
		Button closeBtn = new Button("閉じる");
		buttonList.add(closeBtn);
	}
	/**
	 * メインメソッド
	 * @param args プログラム引数
	 */
	public static void main(String[] args) {
		// 親クラスのメソッドを呼び出す、これは上のstart()を呼び出す。
		launch();
	}

	/**
	 * JavaFX版のハローワールド実装用のメソッドになります。
	 * @return 画面に出力する文字列
	 */
	public String myFirstProgram() {
		// この「hyoji = ""」を「"hyoji = "Hello World"」と修正してください。
		String hyoji = "Hello World";
		long num = 12345678901L;
		float shosu = 123.09876543f;
		return hyoji;
	}
}

前バージョンのソースに比べて、画面ペインの作成メソッドが全て無くなっています。実質2つのメソッドですが。。。

どこに引っ越したかというと、「JavaBasicPain」「WebLoaderPane」クラスに引越ししました。

各クラスはシンプルにコンストラクタ(private)とインスタンス(getInstance)を取得するメソッドが実装してあります。

JavaBasicPane

/**
 * Copyright (c) 2012-present Lightweight Java Game Library All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * Neither the name Lightweight Java Game Library nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
 */
package jp.zenryoku.fx.pane;

import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;

/**
 * JavaBasic用の画面クラス。
 * Paneクラスを継承して、画面の表示部分を作成します。
 * 
 * @author takunoji
 * 2019/01/28
 */
public class JavaBasicPane extends Pane {
	/** このクラスのインスタンス */
	private static JavaBasicPane instance;
	
	/**
	 * コンストラクタ。
	 * デフォルト設定でのJavaBasic画面を作成します。
	 */
	private JavaBasicPane() {
		// 暗黙的に起動される親クラスのコンストラクタ
		super();
		// レイアウトたて
		VBox vBox = new VBox(5);
		// レイアウト横
		HBox hBox = new HBox(8);
		// ラベルの設定
		Label label = new Label();
		// ハローワールドを出力する
		label.setText("Hello World");
		label.setFont(new Font("RobotRegular", 24));
		vBox.getChildren().add(label);
	
		// 1個目の数値、テキストフィールド
		TextField text1 = new TextField();
		text1.setPrefColumnCount(3);
		text1.setAlignment(Pos.BASELINE_CENTER);
		hBox.getChildren().add(text1);
		// 計算式のラベル
		Label ope = new Label("+");
		hBox.getChildren().add(ope);
	
		// 2個目の数値、テキストフィールド
		TextField text2 = new TextField();
		text1.setPrefColumnCount(3);
		text1.setAlignment(Pos.BASELINE_CENTER);
		hBox.getChildren().add(text2);
	
		// 縦のレイアウトに追加する
		vBox.getChildren().add(hBox);

		// 子供(中身)のペインを追加
		this.getChildren().add(vBox);
	}

	/** 
	 * インスタンを取得する。
	 * このクラスのインスタンスは、必ず1つなので「static」をつけて良い。
	 * @return JavaBasicPane
	 */
	public static JavaBasicPane getInstance() {
		if (instance == null) {
			instance = new JavaBasicPane();
		}
		return instance;
	}
}

インスタンスを取得するメソッドは自分が気に入っている、実装方法です。

シングルトン・パターン

public static JavaBasicPane getInstance() {
    if (instance == null) {
      instance = new JavaBasicPane();
  }
return instance;
}

このクラスのインスタンスが既にあるのならば、フィールドにあるインスタンスを返すメソッドになっています。つまりコンストラクタは一回しか通らない。。。

そして、フィールド変数には自分自身(JavaBasicPane)のインスタンスが格納できるようになっています。

こうすると、インスタンスが沢山できて余計なメモリを食わないで済みます。

ちなみに、ウェブサーバーにログインするときはインスタンスが1つだと複数人でログインした時に、どのインスタンスがどのユーザーかわからないので、インスタンスが複数になるようにクラスを作ります。したのはサンプルです。

public class LoginClass {
   // ユーザー名
   private String userName;
   // 性別
   private int sex;
   /* ログイン処理メソッド */
   public login() {
     // ログイン用の処理
   }
}

一気にやるとわからなくなるので「WebLoaderPane」は次回にします。