【Java発展学習14-15日目】設計原則とGoFデザインパターン、モジュールシステム

# 6つの設計原則

| 分類 | 設計原則 | 内容 |
|:--|:--|:--|
| コード記述 | DRY(Don't Repeat Yourself) | 繰り返さない |
|   | PIE(Program Intently and Expressively) | 意味・意図の明確化 |
| クラス設計 | SRP(Single Responsibility Principle) | 単一責任原則 |
|   | OCP(Open-Closed Principle) | 開放閉鎖原則 |
| クラス間連携 | SDP(Stable Dependencies Principle) | 安定依存原則 |
|   | ADP(Acyclic Dependencies Principle) | 非循環依存原則 |

## PIE
`PIE`では、「コメント文を取り除いても可読性の高いコード」を目指す。
具体的には、以下の3つの手法をとる。

> 1. 変数名で**役割・目的**を表す
> 2. **マジックナンバー**をfinal定数で命名
> 3. 制御構造の深い処理への命名

## SRP
[参考: 発展学習12日目(メトリクス)](https://qiita.com/b150005/items/927e2713da1e6a353855#%E3%83%A1%E3%83%88%E3%83%AA%E3%82%AF%E3%82%B9)
`SRP`では、「修正時の再テスト範囲が関連部分のみに限定されるクラス」を目指す。
ただし、必要以上の分割はかえって可読性や機能性が落ちるため、**WMCを基準**としてクラスの分割・統合を決定する。

## OCP
`OCP`では、「拡張に対して開放的であり、変更に対して閉鎖的なクラス」を目指す。
具体的には、「**継承**によって拡張可能であり、継承元クラスが変更不要なクラス」を指す。

## SDP
`SDP`では、「上位クラスやUIから遠いクラスなどの、修正頻度が低い安定的なクラスに依存する」ことを目指す。

## ADP
`ADP`では、「クラス間の循環・相互依存による修正の連鎖を抑える」ことを目指す。

***

# GoF(Gang of Four)デザインパターン
[参考1: GoFのデザインパターン](https://qiita.com/i-tanaka730/items/c63c6c22abd1477e0ba0)
[参考2: デザインパターン](https://www.techscore.com/tech/DesignPattern/index.html/)
[参考3: デザインパターン入門](https://www.itsenka.com/contents/development/designpattern/)
[参考4: ぼくにもわかるデザインパターン](https://www.ulsystems.co.jp/topics/028)
数多く存在する設計原則を採用したGoFのデザインパターンは、以下の通り。

| 分類 | デザインパターン | 内容 |
|:--|:--|:--|
| 生成 | Abstract Factory | 共通部品群の生成 |
|   | Builder | 実体化の複雑なインスタンスの生成 |
|   | Factory Method | 部品のインスタンス生成のみ具象ファクトリに委託 |
|   | Prototype | インスタンスの複製 |
|   | Singleton | 単一インスタンスの生成 |
| 構造 | Adapter | 関連のない2つのクラスの結び付け |
|   | Bridge | 機能の「追加」と「実装」を両立 |
|   | Composite | 階層構造の簡素化 |
|   | Decorator | 間接的継承による機能拡張 |
|   | Facade | ファサードによる処理の集約 |
|   | Flyweight | インスタンスの共有 |
|   | Proxy | 代理オブジェクトによる処理 |
| 振る舞い | Chain of Responsibility | 再帰的処理の実行 |
|   | Command | 処理の(クラス)オブジェクト化による処理内容の保持 |
|   | Interpreter | 文法規則クラスによる構文解析 |
|   | Iterator | 集合の構成要素に対するシーケンシャルアクセス |
|   | Mediator | 結合度の低いオブジェクト間の結び付け |
|   | Memento | 状態の記録・読み込み |
|   | Observer | 状態遷移時に処理を実行 |
|   | State | 状態(を表すSingletonオブジェクト)に応じた分岐処理の実行 |
|   | Strategy | 多様なアルゴリズムの実現 |
|   | Template Method | 不確定処理と確定処理の融合 |
|   | Visitor | 互いに利用し合う処理の実行 |

## Abstract Factory

> 1. 抽象ファクトリの抽象メソッドの引数に応じた具象ファクトリの生成
> 2. 具象ファクトリによる共通具象物の生成
> 3. 具象物に応じたメソッドの呼び出し

## Builder

> 1. 具象ビルダを保持する監督者の生成
> 2. 監督者が保持する具象ビルダによる具象物の整形

## Factory Method

> 1. 具象ファクトリの生成
> 2. 具象ファクトリによる具象物の生成
> 3. 具象物に応じたメソッドの呼び出し

## Prototype

> 1. Cloneableインタフェースを継承するプロトタイプインタフェースの定義
> 2. プロトタイプインタフェースの実装クラス(プロトタイプクラス)に応じた`clone()`メソッドの呼び出し
> 3. プロトタイプクラスに応じたメソッドの呼び出し

## Singleton

> 1. コンストラクタをprivateで定義
> 2. private staticなフィールドでオブジェクトを生成
> 3. private staticなフィールドの返却

## Adapter

> 1. 抽象クラスまたはインタフェースの実装クラス(アダプタクラス)のオブジェクトを生成
> 2. アダプタクラスを通じた他クラスのメソッドの呼び出し

## Bridge

> 1. 具象「機能実装」クラスを保持する抽象「機能追加」クラスの生成
> 2. 具象「機能実装」クラスを保持する具象「機能追加」クラスの生成
> 3. 具象「機能追加」クラスを通じたメソッドの呼び出し

## Composite

> 1. 共通の抽象クラスをもつ継承クラスオブジェクトの生成
> 2. 継承クラスを通じたメソッドの呼び出し

## Decorator

> 1. 共通の抽象クラスをもつ継承クラスオブジェクトの生成
> 2. 継承クラスを通じたメソッドの呼び出し
> <br>※ Compositeとの違いは、共通の抽象クラスをもつ別の派生関係にあるクラスのメソッドを呼び出す点にある。

## Facade

> 利用クラスを束ねるファサードクラスを通じたメソッドの呼び出し

## Flyweight

> 1. ファクトリクラスにSingletonパターンを適用
> 2. 具体物をMapプールに格納しておき、適宜プール内で呼び出して再利用

## Proxy

> 1. 共通の抽象主体クラスを継承するプロキシクラス・具象主体クラスの生成<br>※プロキシクラスは具象主体クラスを内部的に保持
> 2. プロキシクラス内部の具象主体クラスがnull(未生成)であれば代理処理を行い、具象主体クラスを生成
> 3. プロキシクラス内部の具象主体クラスが存在すれば具象主体クラスのメソッドの呼び出し

## Chain of Responsibility

> 1. 抽象ハンドラクラス型のフィールド(ハンドラフィールド)を保持する具体ハンドラクラスの生成
> 2. ハンドラフィールドに具体ハンドラクラスをセット
> 3. ハンドラフィールドを再帰的に利用するメソッドの呼び出し

## Command

> 1. 共通の抽象コマンドクラスを継承する具象コマンドクラスの生成
> 2. 具象コマンドクラスに応じたメソッドの呼び出し

## Interpreter

> 規則と一対一対応したクラスを利用した構文解析

## Iterator

> 1. コレクションの生成
> 2. コレクションを保持するイテレータクラスの生成
> 3. イテレータクラスを通じたコレクション内の構成要素への順次アクセス

## Mediator

> 1. 全ての具象同僚クラスをコレクションで保持する具象仲介者クラスの生成
> 2. 同一の具象仲介者クラスを保持する具象同僚クラスの生成
> 3. 具象同僚クラスを通じた、具象仲介者クラスのメソッドの呼び出し

## Memento

> 1. ある時点でのフィールド情報を保持するメメントクラスの生成
> 2. メメントオブジェクトをコレクションに格納し、任意の時点での記録を反映

## Observer

> 1. 具象観察対象クラスのフィールド情報を変更
> 2. 抽象観察対象クラスからオブザーバクラスのメソッドを呼び出し

## State

> 1. Singletonパターンを採用した状態クラスオブジェクトの生成
> 2. 状態に応じた分岐処理の実行

## Strategy

> 1. 具象戦略クラスを保持する文脈クラスの生成
> 2. 文脈クラスを通じた具象戦略クラスのメソッドの呼び出し

## Template Method

> 1. 抽象クラスでprotectedな抽象メソッドを含む、finalな処理の流れを記述
> 2. 具象クラスで抽象メソッドの処理を記述

## Visitor

> 1. 具象受入者クラスで、引数に訪問者クラスをとる訪問者クラスのメソッドの呼び出し
> 2. 具象訪問者クラスで、引数に受入者クラスをとる受入者クラスのメソッドの呼び出し

***

# モジュール定義
モジュールに関する定義は、JARファイル直下に配置する`module-info.java`ファイルに記述する。

## パッケージのアクセス制御
パッケージごとの外部アクセス制御は`exports文`または`opens文`で記述する。

| アクセス制御子 | 通常アクセス | リフレクション |
|:--|:-:|:-:|
| exports | o | o |
| opens | x | o |

## 依存モジュールの指定
モジュールが外部モジュールに依存する場合、`requires文`で外部モジュールを指定する。

## サンプルコード

```java:module-info.java
module jp.advance.b150005 {
    exports <公開パッケージ>;
    opens <リフレクションのみ許可する限定公開パッケージ>;
    requires <依存モジュール>;
}
```

## モジュールパスを指定したJARファイルの利用

```zsh
# モジュールパスを指定したコンパイル
% javac -p <モジュールパス> <ソースファイル>

# モジュールパスを指定したクラスファイルの実行
% java -p <モジュールパス> <メインクラスのFQCN>
```

***

# 用語集

| 用語 | 内容 |
|:--|:--|
| マジックナンバー(magic number) | コード中に登場する、意味が不明瞭な数値リテラル。 |
| ソフトウェアフレームワーク(software framework) | 独自定義したクラスを呼び出すクラス群。 |
| モジュールシステム(module system) | JARファイルの公開にあたって、公開するパッケージを制御する仕組み。 |
| モジュールパス(module path) | モジュールシステムを利用するJARファイルの格納先ディレクトリパス。 |
|   |   |
|   |   |
|   |   |
|   |   |
|   |   |
|   |   |