2016年9月29日木曜日

Pathの機能(Pathとファイルの相互変換)

みなさん。 こんばんは。

今日はPathとFileの相互変換について見ていきましょう。

Java7よりPathインターフェース機能が導入されても、Fileクラスしかライブラリが対応していない

ことはよくあることです。

そのため、PathオブジェクトとFileオブジェクトが相互変換しないといけないニーズがあります。

ではさっそくどんな感じか見てみましょう。

// Pathオブジェクトの生成
Path path = Paths.get("C:/Users/var.txt"); 

// PathオブジェクトからFileオブジェクトへの変換
File file = path.toFile();

// FileオブジェクトからPathオブジェクトへの変換
Path path_file = file.toPath();
if'( path.equals(path_file) ) {
          System.out.println("同じです");
}else{
          System.out.println("違います");
}



toFile()メソッドでFileオブジェクトに変換、toPath()メソッドでPathオブジェクトに変換できます。

変換したFileオブジェクトで対応するライブラリで使用できます。

人気ブログランキングへ

2016年9月28日水曜日

Pathの機能(親ディレクトリの取得)

みなさん。 こんばんは。

機能はPathの機能で絶対パスに変換と、パスの正規化について見てみました。

今日は指定したPathの親ディレクトリを取得する機能を見ていきましょう。

JavaSE6での親ディレクトリの取得方法

File file = new File("C:\Users\\kumeda\\test.txt");
// 親ディレクトリの取得
String parentDirName = file.getParent(); // C:\Users\kumeda
// 親ディレクトリを表すFileオブジェクトの取得
File parentFileDir = file.getParentFile(); // C:\Users\kumeda

Path機能を利用した親ディレクトリの取得

Path path = Paths.get("C:\Users\\kumeda\\test.txt");
// 親パスの取得
Path parentPath = path.getParent(); // C:\Users\kumeda
// リートパスの取得
Path rootPath = path.getRoot(); // C:\

getParent()メソッドやgetRoot()メソッドなど名前からどんな機能か分かりやすいですね。

親ディレクトリを取得する処理は色んな場面で使われそうですね。

明日はPathとFileの相互変換について書いていきます。

それではまた☆


人気ブログランキングへ

2016年9月27日火曜日

Pathの機能(絶対パス取得)

みなさん。こんばんは。

今日はJavaSE7から導入されたPathインターフェースの絶対パス取得について

JavaSE6の方法と比較しながら見てきましょう。

まず相対パスから絶対パスに変換する処理
今までのJavaSE6の絶対パスの取得方法は

File file = new File("var.txt"); // ファイルオブジェクトの生成
String absolutePath = file.getAbsolutePath(); // 絶対パスの取得

JavaSE7のパスインターフェースの機能を使い絶対パスを取得する方法は

Path path = Paths.get("var.txt"); // パスオブジェクトの生成
Path absolutePath = path.toAbsolutePath();

なお、カレントディレクトリを表す "." や親ディレクトリを表す ".." を含む場合、

以下のように記述することでパスを正規化できます。

JavaSE6

File file = new File("C:\\Users\\kume\\..\\test.txt");
String path = file.getCanonicalPath(); // 正規化したパスを取得
System.out.println(path); // C:\Users\test.txt
File normalized = file.getCanonicalFile(); // C:\Users\test.txt

JavaSE7

Path path = Paths.get(".var.txt");
path = path.normalize(); // normalizeメソッドは冗長なパスを簡潔にするメソッド
Path absolutePath = path.toAbsolutePath(); // 絶対パスに変換
System.out.println(absolutePath); // C:\Users\var.txt

normalize()メソッドを経ずに絶対パスに変換した場合、「C:\Users\.\var.txt」と表示されます。

今日はここまでにしておきましょう。

明日もPathインターフェース機能の続きを見てみます。


人気ブログランキングへ

2016年9月26日月曜日

新しいファイルシステム

みなさん。 こんばんは。

今日は新しいファイルシステムについて書いていきます。

java SE 6まではファイルを表すクラスはFileクラスを使用していましたが、Java SE 7からは

java.nio.file.Pathインターフェースを使用するようになりました。

今までのファイル生成は

File file = new File("C:/src/var.txt");

にて生成していきましたが、


これからは

Path path = Paths.get("C:/src/var.txt");

でPathオブジェクトを生成します。

Pathオブジェクトの機能についてはこれからまた書いていきますね。


人気ブログランキングへ

2016年9月17日土曜日

java資格試験の勉強

みなさん こんにちは。
今日は資格試験について書いていきます。
よくjavaの開発者は資格試験はあまり役に立たないと言います。
本当にそうでしょうか?
資格試験はどちらかというと、理論に関する試験で、実務は実際のコーディングです。
でも理論が分かってないと、実際、どのようにコーディングしていったら良いか?とか、バグが出たときに、例えば、javaのtry with resources 文が内部的にどのように動作してるか分からずにデバッグに時間がかかったりと、著しく生産性が下がったりします。
自分は実務でコーディングしていますが、資格試験の問題を解いてみると、間違いが多く、いかに理論が分かってないかと言うことを認識させられました。
生産性を上げるためには、資格試験は効率の良い学習法であると感じました。

人気ブログランキングへ

2016年9月16日金曜日

リソースの自動クローズ

みなさん。 こんばんは。

今日はリソースの自動クローズを読みました。

今までのリソースのクローズは煩雑でコードが読みづらかったですが、

Java SE 7で導入されたtry with resources文で簡潔に書けるようになりました。

またtry with resources構文を使用すると、ファイルなどのリソースのクローズ処理を

自動で行ってくれます。

今までのサンプルソース

public class ReadSample {
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            // リソースのオープン
            // リソースの処理
        } catch (FileNotFoundException e) {
            // 例外処理
        } catch (IOException e) {
            // 例外処理
        } finally {
        // クローズ処理
            if (br != null)
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}

クローズ処理が煩雑ですね。

try with resources文

try (// リソースのオープン) {
            // リソースの処理
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

クローズ処理が無くなって随分簡潔になりましたね。

明日から帰省の関係で読書が出来ませんが、なるべく更新していきたいと思います。

人気ブログランキングへ

2016年9月14日水曜日

ジェネリクス型パラメータの省略

みなさん。 こんばんは。

今日は第1章「小さな言語使用の変更」の「ジェネリクス型パラメータの省略」を読みました。

従来のジェネリクスを使用したクラスのオブジェクトを生成する場合

List<String> list = new ArrayList<String>();

上記のように左右2か所に型パラメータを記述していました。

JavaSE 7 からこのように簡潔に書けるようになりました。 

List<String> list = new ArrayList<>(); // 右辺の型パラメータの省略

この機能は、インスタンスへの参照を保持する変数がどのような型変数で宣言しているかを

コンパイラが判断し、同じ型を使ってインスタンス生成時の型変数を決定するというものです。

このような機能を「型推論」と呼びます。

型パラメータの省略が使える箇所
・変数の初期化   List<Integer> list = new ArrayList<>():
・三項演算子       List<String> list = flg ? new ArrayList<>(); : new LinkedList<>():
・メソッドの引数    String result = getResult(new ArrayList<>());
・メソッドの戻り値  List<String> getResultList(){ return new ArrayList<>(); }
・仮型パラメータを使用した変数への代入
public class Generics<T> {
private List<T> list;
public Generics() {
list = new ArrayList<>();
}

型パラメータの省略が使えない箇所
・匿名クラス

Callable<String> call = new Callable<> { ,,,} // コンパイルエラー

感想として実装するときに記述が少なくなるのは良いですが、慣れないうちは従来のジェネリクス

を使用したオブジェクト生成になってしまいそう。。



人気ブログランキングへ

2016年9月13日火曜日

適切な型による例外の再スロー

みなさん。 こんばんは。

今日は第1章「小さな言語使用の変更」の「適切な型による例外の再スロー」を読みました。

前日はマルチキャッチについて書きましたが、適切な型による例外の再スローは、

マルチキャッチを行わずにExceptionでキャッチして、再スロー出来るようになりました。

JavaSE6まではthrowsに記述した例外の型とthrowの例外の型が一致していないと

コンパイルエラーになっていましたが、JavaSE7以降はException型を適切な型に変換します

さっそくどんな内容かソースを見てみましょう。

// 適切な型による例外の再スロー
public void rethrowException(String exceptionName)
  throws FirstException, SecondException { // 何の例外をスローするか指定
    try {
      // ...
    }
    catch (Exception e) { // マルチキャッチを使わずにExceptionでキャッチ
      throw e; // コンパイラは FirstException または SecondException のインスタンスであると判断する
    }
  }

Project Coinではマルチキャッチを使わずにExceptionでキャッチして再スロー出来るので、

より簡潔な記述が出来ますね。

人気ブログランキングへ

2016年9月12日月曜日

マルチキャッチ

みなさん。 こんばんは。

今日は第1章「小さな言語使用の変更」のマルチキャッチを読みました。

・マルチキャッチ

javaSE7よりも前のバージョンでは、例外の種類ごとにcatchブロックを用意して、

例外処理を記述していました。

この方法では同じ例外処理を複数のcatchブロックに記述しなければいけないため、

煩雑なコードになりがちでした。そこで、

」avaSE7から複数の例外を1つのcatchブロックでキャッチできるマルチキャッチが導入されました。

これにより、異なる例外に対して同じ処理となる例外処理は、1つのcatchブロックにまとめることが

できるようになります。

ではソースコードを書いてみましょう。

public class MaltiCatchTest {

public static void main(String[] args) {
String param = args.length > 0 ? args[0] : "a";
try {
new MaltiCatchTest().testException(param);
System.out.println("end");
} catch (SampleAException | SampleBException e) { // 例外処理を一つにまとめる。
System.out.println("Exception Result " + e);
}
}

public void testException(String param) throws SampleAException, SampleBException{
switch (param) {
case "a":
throw new SampleAException();
case "b":
throw new SampleBException();
default :
break;
}
}

class SampleAException extends Exception {

}

class SampleBException extends Exception {

}

}

実行結果
Exception Result MaltiCatchTest$SampleAException

今回はargsパラメータに何も入力していなかったので、「SampleAException」 がthrowされました。

マルチキャッチの制約として継承関係の例外をキャッチできないことです。

以下はコンパイルエラーになります。

public class MaltiCatchTest2 {

public static void main(String[] args) {
String param = args.length > 0 ? args[0] : "a";
try {
new MaltiCatchTest2().testException(param);
System.out.println("end");
} catch (SampleDException | SampleCException e) {
// SampleDException例外とSampleCException例外は継承関係にあるためコンパイルエラー
System.out.println("Exception Result " + e);
}
}

public void testException(String param) throws  SampleCException,SampleDException{
switch (param) {
case "a":
throw new SampleCException();
case "b":
throw new SampleDException();
default :
break;
}
}
class SampleCException extends Exception {

}

class SampleDException extends SampleCException {

}
}

感想として、例外がまとめてかけるようになったのでコードがすっきりしましたね。


人気ブログランキングへ

2016年9月11日日曜日

switch文での文字列使用

みなさん こんばんは。

今日は第1章の 「小さな言語使用の変更 Project Coin」 の途中まで読みました。

冒頭で何故プロジェクト名がCoinなのか?と言う名前の由来が書かれていて

そういうことなのか、と思いました。

そもそもProject Coin で何が変更になったのでしょうか。

・switch文での文字列が使用出来るようになった。

今まではif else 文で条件分岐していたところをswitch文で記述出来ることによりスマートに書ける

ようになった。気をつけたいところは文字列にNullが渡された時にNullPointerExceptionの例外が発

生するので事前にNullチェックが必要であること。

こんな感じで。。

if ( str == null ) {
// ・・・Nullの場合の処理
} else switch(str) {
case "test" :
// Null以外の場合の処理
break;
}

・2進数リテラルが使えるようになりました。

今までは10進数、8進数、16進数の3種類でしたが、2進数を使えることで計算の幅が広がりましたね。
10進数の「3」を2進数で表記すると = 0b11 2進数の表記は先頭に0bが付きます。

・数値リテラルで区切り文字(アンダースコア)が使えるようになりました。

今までは桁数が多くなると可読性が悪くなってました。

こんな感じ。。

int i = 1000000000;

この数値をパッと見でいくらなのかを把握するのは難しかったのですが、

int i = 1_000_000_000;

こんな感じでアンダースコアを付けることにより可読性が向上しました。

今日はここまで読みました。

感想としてswitch文は簡単な、if else文の代替えとして使えそう。

複雑な条件分岐は従来通りのif文を使うことになるでしょう。

2進数の計算処理は頻繁に使うことは無いでしょうが、今後使うケースがあるでしょう。

数値リテラルの区切り文字は個人的にはあまり可読性が良くなったかと言われると??

な感じです。


人気ブログランキングへ

現場で使える最新Java SE 7/8 速攻入門の読書日記①

みなさん。 こんばんは。

デザインパターンの生成に関するパターンが一段落したので、

今回は趣向を変えて読書日記を始めたいと思います。

自分は今までjavaの書籍をインプットばかりしてきたので、アウトプットも兼ねて重要な点を紹介し

ていけたらと思ってます。
今回この書籍を選んだのは、最新のJava言語の説明がとても分かりやすく

個人的に気に入ったことと、職場ではまだJavaSE6を使っているので

最新のJava言語を習得したいという意向がありました。

今回は「現場で使える最新Java SE 7/8 速攻入門」を読んでいきます。

以下 現場で使える最新Java SE 7/8 速攻入門の章構成
(目次)
はじめに
  • Chapter 1 小さな言語仕様の変更 ――Project Coin
  • 1.1 小さな言語仕様の変更
  • 1.2 switch文での文字列の使用
  • 1.3 2進数リテラル
  • 1.4 数値リテラルの区切り文字
  • 1.5 マルチキャッチ
  • 1.6 適切な型による例外の再スロー
  • 1.7 ジェネリクス型パラメータの省略
    • 1.7.1 ダイヤモンド演算子が使用可能な箇所
    • 1.7.2 ダイヤモンド演算子が使用できない箇所
  • 1.8 リソースの自動クローズ
    • 1.8.1 複数リソースの自動クローズ
  • 1.9 安全な可変長引数メソッド
  • 1.10 まとめ

Chapter 2 新しいファイルシステムインタフェース ――NIO.2

  • 2.1 新しいファイルシステムインタフェース
  • 2.2 ファイルシステムとパス
    • 2.2.1 Pathオブジェクトの生成
    • 2.2.2 Pathの機能
    • 2.2.3 PathとFileの相互変換
  • 2.3 Pathに対する操作
    • 2.3.1 コピー
    • 2.3.2 移動/名前の変更
    • 2.3.3 削除
    • 2.3.4 ファイル/ディレクトリの作成
    • 2.3.5 リンク
    • 2.3.6 ファイルの入出力
  • 2.4 アトリビュート
    • 2.4.1 Filesクラスのアトリビュート関連メソッド
    • 2.4.2 名前を指定したアトリビュートの取得/設定
    • 2.4.3 複数のアトリビュートの取得/設定
  • 2.5 ファイルツリーの走査
    • 2.5.1 ディレクトリのコピー
  • 2.6 ディレクトリの監視
  • 2.7 まとめ

Chapter 3 ラムダ式による新しいプログラミングスタイル

  • 3.1 ラムダ式と新しいプログラミングスタイル
  • 3.2 関数型インタフェース
    • 3.2.1 関数型インタフェースとは?
    • 3.2.2 汎用の関数型インタフェース
    • 3.2.3 関数型インタフェースの作成
  • 3.3 ラムダ式
    • 3.3.1 引数の型,丸カッコの省略
    • 3.3.2 波カッコとreturn文の省略
    • 3.3.3 実質的final
    • 3.3.4 ラムダ式の注意点
  • 3.4 デフォルトメソッド
    • 3.4.1 デフォルトメソッドの使用
    • 3.4.2 デフォルトメソッドと多重継承
  • 3.5 インタフェースのstaticメソッド
  • 3.6 メソッド参照
    • 3.6.1 クラスメソッド参照
    • 3.6.2 インスタンスメソッド参照
    • 3.6.3 コンストラクタ参照
  • 3.7 ラムダ式の使い道
    • 3.7.1 高階関数
    • 3.7.2 関数合成
  • 3.8 まとめ

Chapter 4 Stream APIによる内部イテレータ

  • 4.1 内部イテレーションとStream API
  • 4.2 内部イテレータ
  • 4.3 Stream API
    • 4.3.1 ストリームの処理手順
    • 4.3.2 ストリームの種類
  • 4.4 ストリームの生成
    • 4.4.1 コレクション,配列からの生成
    • 4.4.2 I/Oからのストリーム生成
    • 4.4.3 ストリームのファクトリメソッド
    • 4.4.4 その他のストリーム生成
  • 4.5 ストリームの中間操作
    • 4.5.1 プリミティブ型に対応したストリームに固有の中間操作
  • 4.6 ストリームの終端操作
  • 4.7 nullチェックとOptionalクラス
    • 4.7.1 生成
    • 4.7.2 値の取得
    • 4.7.3 その他のメソッド
    • 4.7.4 Optionalクラスの用途
  • 4.8 Stream APIを使用した従来のコードの書き換え例
    • 4.8.1 条件に合致する要素を取り出す
    • 4.8.2 要素から他の情報を抽出
    • 4.8.3 要素から他の情報を抽出し,平坦化
    • 4.8.4 要素のグルーピング
    • 4.8.5 要素を平坦化し,集計
    • 4.8.6 顧客ごとの購買履歴の統計をとる
  • 4.9 パラレルストリーム
    • 4.9.1 パラレルストリームの取得
    • 4.9.2 処理順序に依存する記述
    • 4.9.3 パラレルストリームに特有のメソッド
    • 4.9.4 Fork/Join Framework
    • 4.9.5 パラレルストリームの動作
    • 4.9.6 パラレルストリームの注意点
  • 4.10 まとめ

Chapter 5 ISO 8601とDate and Time API

  • 5.1 新しい日時のためのAPI
  • 5.2 ISO 8601
    • 5.2.1 協定世界時?UTC
    • 5.2.2 UTCと地方時の時差
    • 5.2.3 暦
    • 5.2.4 日時表記
    • 5.2.5 日付の表記
    • 5.2.6 時刻の表記
    • 5.2.7 日付と時刻の表記
    • 5.2.8 時間長と時間間隔の表記
    • 5.2.9 JIS X 0301による拡張
  • 5.3 Date and Time API
    • 5.3.1 日時クラスの概要
    • 5.3.2 LocalDateTimeクラス
    • 5.3.3 時差とタイムゾーン
    • 5.3.4 OffsetDateTimeクラス
    • 5.3.5 ZonedDateTimeクラス
    • 5.3.6 日時クラスの変換
    • 5.3.7 Dateクラス,Calendarクラスとの変換
    • 5.3.8 日時フォーマット
    • 5.3.9 時間間隔
    • 5.3.10 暦
  • 5.4 まとめ
  • おわりに

章構成を見た感じだと新しいファイルシステムやDate Time APIなど、どんなことが変わったのか気になりますね。

次からは章ごとに読んだ感想や前のJavaバージョンとどの点が良くなったか等の視点で書いていきたいです。

人気ブログランキングへ

2016年9月10日土曜日

prototypeパターン

今日はprototypeパターンを見ていきましょう。

prototypeパターンとはざっくり言うと、原型となるオブジェクトを複製して新たなオブジェクトを生成

するパターンと言えるでしょうか。

Javaオブジェクトは、メソッドClone()を使って複製することができます。

Jobj j1 = (Jobj)j0.clone();

メソッドclone()は、常にObject型を返しますのでクローン生成しようとしているオブジェクトの実際の

型にキャストしなければなりません。このメソッドには下記の制約があります。

・ protetedなメソッドであり、同じクラスあるいはサブクラスからのみ呼び出せる。
・インターフェースCloneableをimplementsすると宣言されたオブジェクトだけがクローン生成できる。

クラスObjectのメソッドclone()はprotectedですから、具象クラス中にpublicなクローンメソッドを作り

そこからprotectedなclone()にアクセスします。

簡単な例を見てみましょう。

// prototype
public class SoccerSenshu implements Cloneable {

private String name;

public SoccerSenshu(String name) {
this.name = name;
}

public Object cloneMe() throws CloneNotSupportedException {
return super.clone();
}

public String toString() {
return "選手名は " + name;
}
}

// クライアントクラス
public class Client_Cloneable {

public static void main(String args[]) throws CloneNotSupportedException {
SoccerSenshu senshu1 = new SoccerSenshu("マラドナ");
SoccerSenshu senshu2 = (SoccerSenshu) senshu1.cloneMe(); // クローン
System.out.println(senshu1);
System.out.println(senshu2);
}
}

実行結果
選手名は マラドナ
選手名は マラドナ

同じオブジェクトがコピーされましたね。

しかしそもそも何故複製が必要なのでしょうか?

例としてある答えを得るのに、大規模なデータベースに数多くの問い合わせが必要となる場合、

その答えがテーブルあるいはResultSetとして一旦得られれば、それを操作することによって

(他に問い合わせを発行することなく)別の答えも導き出せるでしょう。

このように負荷の大きい作業を軽減する目的で使われることが多いです。

人気ブログランキングへ


2016年9月8日木曜日

Builderパターン

みなさん こんばんは。

今日はBuilderパターンを見ていきましょう。

Builderパターンとはその名の通り建築物を作るかのようにオブジェクトを作るパターンと言いま

しょうか。

言葉で説明するより、さっそくどんな感じなのか見ていきましょう。
以下、Builderパターンのクラス図

// 車クラス クラス図Productに該当
public class Car {

private String engin;

private String taiya;

private String name;

public String getEngin() {
return engin;
}

public void setEngin(String engin) {
this.engin = engin;
}

public String getTaiya() {
return taiya;
}

public void setTaiya(String taiya) {
this.taiya = taiya;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String toString(){
return "「 チーム名 "+getName()+" : エンジン "+getEngin()+" : タイヤ "+getTaiya()+" 」";
}
}

// ビルダー クラス図Builderに該当
public interface Builder {

void buildEngin();

void buildTaiya();

void buildName();

Car getResult();
}

//ビルダー実装クラス1 クラス図ConcreateBuilderに該当
public class McLarenBulder implements Builder {

private Car car;

public McLarenBulder(){
this.car = new Car();
}

@Override
public void buildEngin() {
this.car.setEngin("ホンダ");
}

@Override
public void buildTaiya() {
this.car.setTaiya("ブリジストン");
}

@Override
public void buildName() {
this.car.setName("マクラーレン");
}

@Override
public Car getResult() {
return this.car;
}
}

// ビルダー実装クラス2 クラス図ConcreateBuilderに該当
public class FerrariBuilder implements Builder {

private Car car;

public FerrariBuilder(){
this.car = new Car();
}
@Override
public void buildEngin() {
this.car.setEngin("フェラーリ");
}

@Override
public void buildTaiya() {
this.car.setTaiya("ピレリ");
}

@Override
public void buildName() {
this.car.setName("フェラーリ");
}

@Override
public Car getResult() {
return this.car;
}
}

// ディレクター クラス図Directorに該当
public class Director {

private Builder builder; // Has-a関係

public Director(Builder builder){
this.builder = builder;
}

public Car constructFoumura1(){
this.builder.buildEngin();
this.builder.buildTaiya();
this.builder.buildName();
return this.builder.getResult();
}
}

// クライアントクラス
public class Client_BuilderTest {

public static void main(String[] args) {
Director d1 = new Director(new McLarenBulder());
Director d2 = new Director(new FerrariBuilder());
Car mcLaren = d1.constructFoumura1();
Car ferrari = d2.constructFoumura1();
System.out.println(mcLaren);
System.out.println(ferrari);
}
}

実行結果
「 チーム名 マクラーレン : エンジン ホンダ : タイヤ ブリジストン 」
「 チーム名 フェラーリ : エンジン フェラーリ : タイヤ ピレリ 」

クライアントクラスでマクラーレンとフェラーリBuilderをDirectorに渡して、

DirectorがconcreateFoumura1()メソッドを呼び出すと、エンジンとタイヤの付いたF1カーが

返却されます。本例は簡単な例でしたが、本来はもっと複雑な複合構造のオブジェクト生成物が返

却されるでしょう。




人気ブログランキングへ

2016年9月7日水曜日

Singletonパターン

今回はSingletonパターンを紹介しますね。

Singletonパターンはクラスのインスタンスをアプリケーション内で一つだけ生成するパターンです。

クラスのインスタンスを一つだけに制限したい例はいくらかあるでしょう。

例えば、ファイルアクセス、ロギング処理、キャッシュ、コネクションプールなどでしょうか。

実際これらのオブジェクトを2つ以上インスタンス化したら、

プログラムの誤動作やつじつまの合わない結果といったあらゆる問題が起きてしまいます。

ではどんな感じで実装するのか見てみましょう。

// シングルトン
public class Singleton {
private static Singleton instance = new Singleton(); // static初期化でインスタンス生成
private Singleton() { }; // コンストラクタはprivateであること
public static Singleton getInstance() { // インスタンスの取得はこのstaticメソッドで取得
return instance;
}
public void print(String s) {
System.out.println(s);
}
}

// メインクラス
public class Client {
public Client() {
Singleton s1 = Singleton.getInstance();  // 1回目
s1.print("こんにちは。シングルトン1");
Singleton s2 = Singleton.getInstance();  // 2回目
s2.print("こんばんは。シングルトン2");
if (s1 == s2 ) {
System.out.println("同じインスタンス");
}
System.out.println("シングルトン1" + s1);
System.out.println("シングルトン2" + s2);
}

public static void main(String[] args) {
new Client();
}
}

ここではシングルトンインスタンスを2回要求した後で、
同一のインスタンスかどうかを s1 == s2 によってチェックしています。
このプログラム実行結果は下記になりました。

・実行結果
こんにちは。シングルトン1
こんばんは。シングルトン2
同じインスタンス
シングルトン1jp.co.kouji.umeda.core.Singleton@2e4f7bc2
シングルトン2jp.co.kouji.umeda.core.Singleton@2e4f7bc2

Singleton.getInstance();を二回呼び出してますが、

実行結果はシングルトン1とシングルトン2が同じインスタンスになってますね。

ここでは簡易的な例にしましたが通常は上記で記載されている通り、

ロギングやキャッシュなどのアクセスオブジェクトとして使われたりします。


人気ブログランキングへ

2016年9月6日火曜日

Abstract Factoryパターン

みなさん こんばんは。

今回はAbstract Factoryパターンについて書いていきます。

Abstract Factoryパターンは1つのFactoryクラスに複数のFactoryメソッドを持たせ

主に実装環境に依存するような場合などに利用されます。

Abstract Factoryパターンの古典的な例として、WindowsやMacintoshなど、

複数のルック&フィールドのユーザインターフェースをまとめて切り替えるような例で使われたりします。

グループ化されたオブジェクト単位で切り替える場合に利用されるパターンがAbstract Factoryパターンと言えるでしょうか。

では簡単な例を見てみましょう。


// Abstract Factory基底インターフェース
public interface AbstractFactory {
    public Product1 createProduct1();
    public Product2 createProduct2();
}

// 製品基底インターフェース1
public interface Product1 {
    public void sayHello();
}

// 製品基底インターフェース2
public interface Product2 {
    public void goodNight();
}

// 製品実装クラス1
public class ConcreateProduct1 implements Product1 {
    public void sayHell(){
        System.out.println("こんにちは。こちらが製品1になります。");
    }
}

// 製品実装クラス2
public class ConcreateProduct2 implements Product2 {
    public void goodNight(){
        System.out.println("こんばんは。こちらが製品2になります。");
    }
}

// AbstractFactory実装クラス
public class ConcreateFactory implements AbstractFactory {
    public Product1 createProduct1() {
        return new ConcreateProduct1();
    }
    public Product2 createProduct2() {
        return new ConcreateProduct2();
    }
}

// クライアントクラス
public class Client {
    public static void main(String args[]) {
         AbstractFactory factory = new ConcreateFactory(); 
         Product1 p1 = factory.createProduct1();
         Product2 p2 = factory.createProduct2();
         p1.sayHello();
         p2.goodNight();
    }
}

クラス図の通り実装してみました。
Abstract Factoryクラスの利点は、新たな(ファクトリ用の)サブクラスを容易に追加できる点に
あると思います。

人気ブログランキングへ

2016年9月5日月曜日

Factory Methodパターン

みなさん、こんばんは。

前回はもっとも簡単なSimple Factoryパターンを案内しましたが、

今回のFactory MethodパターンはSimple Factoryパターンを拡張した内容と言えるでしょうか。

Factory Methodパターンはそのオブジェクトを生成するかを各サブクラスに決定させる抽象クラスを定義します。

言葉での前置きよりさっそく実例を見ていきましょうか。
以下はクラス図になります。



ソースコードで実装するとこんな感じでしょうか。

// Factory Method抽象クラス
public abstract class Creator {
         public abstract Product factoryMethod();
}
// Factory Method具象クラス
public class ConcreteCreator extends Creator {
         public Product factoryMethod(){
                 return new ConcreteProduct();
         }
}
// 製品抽象クラス
public abstract class Product {
         public abstract void hell();
}
// 製品具象クラス
public class ConcreateProduct extends Product {
          public void hello() {
                System.out.println("Hello World");
}}
// メインクラス
public class FactoryMethodMain {
           public static void main(String args[]) {
                 // 引数args[0]には「ConcreateCreator」が設定されていること
                 Creator creator = Class.forName(args[0]).newInstance();
                 Product product = creator.factoryMethod();
                 product.hello();
            }
}

では、どういう場合にFactory Methodを使うべきでしょうか?

考えられる状況として

・これはSimple Factoryパターンにも言えますが、
 生成すべきオブジェクトのクラスが予測できない場合。
・生成すべきオブジェクトをサブクラスによって特定する場合。
・どのクラスのオブジェクトを生成すべきかに関する知識を局所化したい場合。

デメリットとしては、生成するオブジェクトが増えるごとにファクトリーメソッドを持ったクラスが増えてしまうことではないでしょうか。
その問題もDIコンテナを導入することで解決出来ますが、DIコンテナが考えられた背景を学ぶのは損ではないと思います。
人気ブログランキングへ

2016年9月4日日曜日

Simple Factoryパターン

システム開発を行う上での問題はいかに結合度を低くするかにあるでしょう。

デザインパターンでは様々な生成に関するパターンが作られてきました。

そこで今回はSimple Factoryパターンを見ていきましょう。

このパターンは、与えられたデータに基づいて、

複数の可能なクラスの中の1つのクラスのインスンスを返します。

Simple Factoryを理解するために、まずはソースを見て下さい。

// 基底クラス
abstract class X {       abstract public void do_X();}
// サブクラス
public class XY extends X {
         public void do_X() {
                  int i = 5;
         }
}
// サブクラス
public class XZ extends X {
          public void do_X {
                   int i = 6;
          }
}
// 引数で渡される値に基づいて、どちらかのサブクラスのインスタンスを返します。
public class XFactory {
          public X getClass(int index) {
                  if ( index == 1) {
                       return new XY();
                  } else {
                       return new XZ();
                  }
          }
}
// テストクラス
public class TEST {
            public static void main(String args[]) {
                    int index = 1;
                    XFactory factory = new XFactory();
                    X x = factory.getClass(index);
                    x.do_X();
            }
}
このソースは、Xは基底クラスで、XYとXZはXのサブクラスになっています。

クラスXFactoryは、引数で渡される値に基づいて、

これらのサブクラスのどちらのインスタンスを返すべきか判断します。

ここでは、メソッドgetClass()がそうです。このメソッドは何らかの値を引数で受け取り、

その値に基づいてクラスXの何らかの(XYもしくはXZの)インスタンスを返すのです。

クラスXYならびにXZは同じ(実装内容が異なりますが)メソッドdo_X()を持っているため、

どちらのクラスのインスタンスを返すべきかは、完全にFactoryクラス(ここではXFactory)

に任されるのです。

以上がSimple Factoryパターンの基本原理です。

どのクラスのインスタンスを返すべきかを判断して返す「抽象」を作るわけです。

返されたインスタンスに対しては、それが実際にどのサブクラスに属するかを意識することなく

メソッドを呼び出せます。個々のクラスの具体的はメソッドに依存することがなくなります。

DIコンテナ全盛の中で生成に関するパターンを学ぶ必要があるのかと言われたりもしますが、

プログラムの結合度を減らすために何故その技術が出来たのかの経緯を知るためには

必要であると感じました。


人気ブログランキングへ


デザインパターンについて

突然ですが、皆さんはデザインパターンを利用してプログラミングしてますでしょうか?

自分が今まで多数のプロジェクトで他の人が書いたソースコードを見てきましたが、

これはデザインパターンを使っているなと思われるソースコードに殆ど出会ったことがありません。

そこでデザインパターンを実際にどう使えば良いのかを考えていきたいと思います。

まずどんなデザインパターンがあるか見てみましょう。

生成に関するパターン
      Simple Factoryパターン
      Factory Methodパターン
      Abstract Factoryパターン
      Singletonパターン
      Builderパターン
      Prototypeパターン

構造に関するパターン
      Adapterパターン
      Bridgeパターン
      Compositeパターン
      Facadeパターン
      Flyweightパターン
      Proxyパターン

振舞に関するパターン
      Chain of Responsibilityパターン
      Commandパターン
      Interpreterパターン
      Mediatorパターン
      Mementoパターン
      Observerバターン
      Stateパターン
      Template Methodパターン
      Visitorパターン

プレゼンテーションパターン
      Model-View-Controllerパターン
      Front Controllerパターン
      View Helperパターン
      Decoratorパターン
      Service to workerパターン
      Composite Viewパターン
      Asynchronous Pageパターン
      Caching Filterパターン
      Resource Poolパターン

ビジネスロジック層のパターン
      Composite Entityパターン
      Entity Facadeパターン

層と層の間の通信のパターン
      Data Transferパターン
      Data Transfer Hashパターン

データベースパターン
      Data Access Objectパターン
      Tuple Tableパターン
      PK Block Generatorパターン

等々。。

昔の人は凄いですね。

これだけあげましたけどまだ沢山のデザインパターンがあります。

次回からはこの中からデザインパターンを見ていくことにしましょう。

人気ブログランキングへ