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

イントロダクション

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

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


リファクタリングの内容

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

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

https://www.youtube.com/watch?v=_9syqIs6-5o&feature=youtu.be

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() {
     // ログイン用の処理
   }
}

<<< 前回 おまけ >>>

投稿者:

takunoji

音響、イベント会場設営業界からIT業界へ転身。現在はJava屋としてサラリーマンをやっている。自称ガテン系プログラマー(笑) Javaプログラミングを布教したい、ラスパイとJavaの相性が良いことに気が付く。 Spring framework, Struts, Seaser, Hibernate, Playframework, JavaEE6, JavaEE7などの現場経験あり。 SQL, VBA, PL/SQL, コマンドプロント, Shellなどもやります。

コメントを残す