javaでのFactory Methodパターン

Factory MethodパターンはTemplate Methodパターンをオブジェクト生成の場面に適用したもので、オブジェクト生成の処理を共通化することができます。

今回は、RPGのキャラクター作成を模したサンプルコードを作成してみました。
キャラクターの職業毎にクラスを分けており、クラス毎に微妙にオブジェクト生成時の処理が異なっていますが、各々のクラスのオブジェクト生成処理を共通化することができています。

【サンプルコード】

・AbstractJob.java

・Warrior.java

・NormalPerson.java

・AbstractJobFactory.java

・WarriorFactory.java

・NormalPersonFactory.java

・CreateJobMain.java

【実行結果】


いかがでしたでしょうか。

前に紹介したTemplate MethodパターンとFactory Methodパターンは似ているので、合わせて覚えておきたいパターンだと思います。
実務でも、「~Factory」という言葉を良く聞きます。「~Factoryはオブジェクトを生成するクラスだ」という知識があるだけでも、開発者同士のコミュニケーションがスムーズになると思います。

では、よいお年を!

javaでのTemplate Methodパターン

Template Methodパターンは、処理(メソッド)の中で共通している箇所を抽象クラスとして抜き出すことで、重複した記述を排除し、更に処理の流れも規定する手法のことを指します。
手続き型言語でも共通する箇所を子メソッドとして抜き出すことをしますが、子メソッドとして抜き出してしまうとその子メソッドの使い方までは規定できず、子メソッドを誤った使い方をされてしまう可能性が出てきてしまいます。

サンプルコードとして、RPGのダメージ計算を模したプログラムを作成してみました。
「ベースのダメージ量に対してランダム化を行い最終的なダメージ量とする」という処理の流れを規定できていることがポイントです。

【サンプルコード】

・AbstractDamageCalc.java

・PhysicsDamageCalc.java

・MagicDamageCalc.java

・DamageCalcMain.java

【実行結果】

 ※第1引数に-1、第2引数に1を指定した場合


いかがでしたでしょうか。

手続き型言語に対するオブジェクト指向型言語の利点として、特定のルールに従ったコーディングを他の開発者にさせやすくなるというものがあり、バグの混入を未然に防ぐことができます。
共通処理の使い方を指定できるTemplate Methodパターンは、その利点が良く分かるパターンの一つだと思います。
抽象クラスの使い方として、このような使い方は覚えておいて損はないと思います。

では、また次回!

javaでのFacadeパターン

Facadeクラスとは、使い方が複雑になっているクラス群をまとめ、使いやすい形のインターフェースとして外部に提供するクラスのことを指します。
デザインパターンでは、このFacadeクラスを利用するパターンをFacadeパターンと呼びます。
(ちなみに、Facadeは「窓口」を意味する単語です)

サンプルコードとして、RPGのダメージ計算を模したプログラムを作成してみました。
RPGのダメージ計算は複雑で、そのRPGに詳しくない人が正しく計算式を実装するのは困難なのですが、Facadeクラスを用いることにより、Facadeクラスの利用者は詳しい知識を持たずとも正しく計算式を実装することが可能となります。

【サンプルコード】

・PhysicsBaseDamageCalc.java

・MagicBaseDamageCalc.java

・DamageRandomize.java

・DamageCalcFacade.java

・DamageCalcMain.java

【実行結果】

 ※第1引数に-1、第2引数に1を指定した場合


いかがでしたでしょうか。

デザインパターンはオブジェクト指向プログラミングのプログラミング手法をまとめたものなのですが、このFacadeパターンは手続き型言語にも応用が可能です。
複雑な処理を共通クラス・共通関数・共通スクリプト等のような形で切り出して利用者側に意識させないようにする、というのは現場でも良く使う手法なので、覚えておいて損はありません。

では、また次回!

javaでのスレッド制御(joinとsynchronized)

javaでは、スレッドを立てて処理を並列に行うことができます。
しかし、並列に処理を行う際、処理順を制御しなければならないことがあります。

処理順の制御方法として基本的な方法として、joinを使う方法とsynchronizedを使う方法があります。
joinを使うことで、スレッドが終わるのを待つことができます。
また、synchronizedを使うことで、複数のスレッドが同じ処理を同時に行わないように制御することができます。

以下は、joinやsynchronizedを使って制御を行うサンプルコードです。
1つのスレッドで5回の処理を行うサンプルであり、そのスレッドを2つ立てます。
また、スレッド間で同一のオブジェクト(staticなオブジェクト)を共有しており、そのオブジェクトでは合計何回処理が行われたのかをカウントしています。

制御を行わない場合は、どちらのスレッドが先に処理するのかが定まりません。また、共有オブジェクトでのカウントを2つのスレッドで同時に行うためにカウントも上手く行きません。
joinによる制御を行う場合は、スレッド1の5回の処理が終わってからスレッド2の処理に移る、という制御が可能になります。
synchronizedによる制御を行う場合は、スレッド1とスレッド2が同時に動いても、共有オブジェクトでのカウントは同時には行われず、上手くカウントすることができます。

【サンプルコード】

・ThreadMain.java

・ThreadBody.java

・ThreadCounter.java

【実行結果】

・そのまま実行した場合

・①のコメントアウトを外した場合(join)

・②のコメントアウトを外した場合(synchronized)


いかがでしたでしょうか。

性能要件を満たすためにスレッドが必要になることがあるのですが、その際にスレッド制御の方法を知らないと処理の同期が取れずに障害になってしまうことが多いです。
今スレッドを使っていなかったとしても、いつ使うようになるかわかりませんので、こういったスレッド制御の方法を知っておいて損はありません。

では、また次回!

単なるstaticとsingletoneパターンの違い

オブジェクト指向プログラミングのプログラミング手法で、「singleton(シングルトン)」と呼ばれる手法があります。
この手法は、プロジェクト内で共通的に使われるインスタンスを1つだけ予め作成し、外部のクラスにはそのインスタンスを使用させる、という手法です。

この手法を学んだ時に「インスタンスを1つにすれば良いなら、クラス変数やメソッドをstaticにするだけで良いのでは?」と思ったので、試しにテストコードを書いてみました。
単純なstaticでは使用者側で好きにインスタンスを作成できる(実態としては1つ)のですが、singletonとしてインスタンスを作成すれば使用者側でのインスタンス作成を防ぎ、明示的にインスタンスを1つにできることを確認しました。

【テストコード】

・StaticMemory.java

・SingletoneMemory.java

・MemoryTestMain.java

【実行結果】


いかがでしたでしょうか。

「singleton」は、GoFの23個のデザインパターンの内の1つに数えられる手法です。
デザインパターンはオブジェクト指向プログラミングのプログラミング手法をまとめたものであり、効率的なプログラミングを行う上で有効ですので、これからも紹介していくと思います。

では、また次回!