開発効率を劇的に上げる!iluwatarのデザインパターンで保守性の高いJavaコードを書く
これは、GitHubで公開されているJavaのデザインパターン集で、「iluwatar/java-design-patterns」 という名前で知られています。
「iluwatar/java-design-patterns」は、単なるコードのコレクションではなく、「設計の知恵」 が詰まったレシピ集です。ソフトウェアエンジニアの視点から、これがどのように役立つかを見ていきましょう。
| ソフトウェアエンジニアのメリット | ラーメンの例え |
| 品質と保守性の向上 | 失敗しない黄金比のスープ:確立されたパターンを使うことで、バグが少なく、他の人が読んでも理解しやすい、変更に強いコードが書けます。 |
| 共通言語の獲得 | 「豚骨スープのように」:チームメイトとの間で「オブザーバー・パターンを使おう」といった共通の用語で設計の意図を伝えられるようになり、コミュニケーションがスムーズになります。 |
| 学習とスキルアップ | 一流の職人の技を学ぶ:デザインパターンの「お手本」が、実際に動作するJavaコードで提供されています。座学ではなく、実例を通してベストプラクティスを学べます。 |
| 車輪の再発明の回避 | 麺の打ち方に時間をかけない:よくある設計上の問題をゼロから解決しようとせず、このパターン集に既に用意されている「型」を適用することで、開発時間を大幅に短縮できます。 |
このライブラリは、既存のプロジェクトに直接「導入」して利用する、というよりは、「設計の学習リソース」 や 「サンプルコードの宝庫」 として参照・利用することが主な使い方になります。
お気に入りのラーメン屋のレシピをゲットするように、まずは手元にコードを持ってきましょう。
ターミナル(コマンドプロンプト)で以下のコマンドを実行します。
git clone https://github.com/iluwatar/java-design-patterns.git
クローンしたプロジェクトを、IntelliJ IDEAやEclipseなどの統合開発環境(IDE)で開きます。このプロジェクトはMavenを使っているので、IDEが自動的に依存関係を解決して、すぐにコードを読み始められるはずです。
プロジェクトのディレクトリ構造を見てみましょう。パターン名ごとにフォルダが分かれているのが分かるはずです。
java-design-patterns
├── src
│ ├── main
│ │ └── java
│ │ └── com
│ │ └── iluwatar
│ │ └── design
│ │ └── patterns
│ │ ├── abstractfactory
│ │ ├── adapter
│ │ ├── builder
│ │ └── ... (他のパターンが続く)
例えば、「abstractfactory」フォルダを開けば、Abstract Factoryパターン の実装例を見ることができます。
ここでは、最も有名で実用的なデザインパターンの一つである 「Factory Method(ファクトリーメソッド)パターン」 を例に、どのようにコードを参照し、学ぶかを解説します。
「具象クラスを直接指定せずに、オブジェクトを生成する方法をサブクラスに任せる」 ためのパターンです。例えるなら、「店によって味が違う『特製トッピング』」 を作るためのレシピです。
このライブラリでは、factory-method フォルダに例があります。
ここでは、ラーメンの「麺」を抽象化してみましょう。
// 抽象製品 (Product) - ラーメンの麺
public interface Noodle {
String taste();
}
醤油ラーメン用の麺と、味噌ラーメン用の麺を作ります。
// 具象製品 (Concrete Product) - 醤油ラーメン用の麺
public class SoySauceNoodle implements Noodle {
@Override
public String taste() {
return "コシのある醤油ラーメン用の麺";
}
}
// 具象製品 (Concrete Product) - 味噌ラーメン用の麺
public class MisoNoodle implements Noodle {
@Override
public String taste() {
return "太くてモチモチの味噌ラーメン用の麺";
}
}
これがFactory Methodの中心です。麺を作るための抽象的な工場(ファクトリー)を定義し、createNoodle() という抽象メソッドを定義します。
// 抽象クリエイター (Creator) - ラーメンの工場
public abstract class RamenFactory {
// Factory Method: オブジェクトを生成するメソッドをサブクラスに任せる
protected abstract Noodle createNoodle();
public Noodle orderNoodle() {
Noodle noodle = createNoodle(); // サブクラスが実装したメソッドを呼び出す
System.out.println("工場で " + noodle.taste() + " が生産されました。");
return noodle;
}
}
醤油ラーメン店と味噌ラーメン店が、それぞれ自分のお店に合った麺を作る工場を実装します。
// 具象クリエイター (Concrete Creator) - 醤油ラーメン工場
public class SoySauceRamenFactory extends RamenFactory {
@Override
protected Noodle createNoodle() {
return new SoySauceNoodle(); // 醤油用の麺を生成
}
}
// 具象クリエイター (Concrete Creator) - 味噌ラーメン工場
public class MisoRamenFactory extends RamenFactory {
@Override
protected Noodle createNoodle() {
return new MisoNoodle(); // 味噌用の麺を生成
}
}
メインのプログラムは、どの具体的な工場を使うか知っているだけで、麺の具体的な作り方(new SoySauceNoodle() など)については知る必要がありません。これが Factory Method の最大の利点です!
public class App {
public static void main(String[] args) {
// 醤油ラーメン工場を使って麺を注文
RamenFactory soySauceFactory = new SoySauceRamenFactory();
Noodle soyNoodle = soySauceFactory.orderNoodle();
// 出力: 工場で コシのある醤油ラーメン用の麺 が生産されました。
// 味噌ラーメン工場を使って麺を注文
RamenFactory misoFactory = new MisoRamenFactory();
Noodle misoNoodle = misoFactory.orderNoodle();
// 出力: 工場で 太くてモチモチの味噌ラーメン用の麺 が生産されました。
}
}
この「iluwatar/java-design-patterns」を使うことは、一流のラーメン職人から「基礎となる設計の型」 を学んでいるのと同じです。