デザインパターン「Observer」

# はじめに
本投稿は[Java言語で学ぶデザインパターン入門](http://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030/ref=sr_1_1?ie=UTF8&qid=1454743284&sr=8-1&keywords=java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80)のデザインパターンをまとめた記事です。今回は***Observerパターン***になります。
[まとめ一覧はこちら](#design_pattern)

# Observerパターン

<p align="center"><img width="220" alt="スクリーンショット 2016-11-03 23.39.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/f325008e-a16a-1c1a-5f94-2faf517902a1.png"></p>

## Observerパターンとは

観察される側(=Subject)と観察する側(=Observer)の2つの役割が存在し、`Subject`の状態が変化した際に`Observer`に通知されるデザインパターンです。そのため、状態変化に応じた処理を記述する時に有効です。
どちらかというと観察よりも通知に重点が置かれており、`Observer`が能動的に通知を待っているので`Publish-Subscribe`パターンと呼ばれることがあります。`Publish`(=発行)と`Subscribe`(=購読)という意味でこちらの方がイメージつきやすいかもしれませんね。
`MVC`(`Model` / `View` / `Controller`)アーキテクチャでいう。`Model`と`View`の関係性に適応される場合が多いです。


## Observerパターンのクラス図
<p align="center"><img width="450" alt="Observerクラス図 2016-02-14 15.53.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/cf57ad97-6607-cfe4-2d5f-28cf68b7932f.png"></p>


- `Subject`と`Observer`の2役のみ
- 状態が変化した際に`Observer`に通知を行う。

## Observerパターンのサンプル

###### 抽象クラス
 - Observer
  - [Observer](#observer)
 - Subject
  -  [NumberGenerator](#number_generator)

###### 具象クラス
- ConcreteObserver
 - [DegitObserver](#degit_observer)
 - [GraphObserver](#graph_observer)
- ConcreteSubject
 - [RandomNumberGenerator](#random_number_generator)

今回のサンンプルは、数を生成する`Subject`を`Observer`が観察し、生成したタイミングで`Observer`がその値を表示するという簡易的なものです。

## `Main`クラス
```java:Main.java
public static void main(String[] args) {
		NumberGenerator generator = new RandomNumberGenerator();
		Observer degitObserver = new DegitObserver();
		Observer graphObserver = new GraphObserver();
		generator.addObserver(degitObserver);
		generator.addObserver(graphObserver);
		generator.execute();
	}
```

ランダムな数を生成する`RandomNumberGenerator`を`degitObserver`と`graphObserver`が観察し、数字が変化したタイミングで`degitObserver`は値を、`graphObserver`が値を簡易グラフで出力します。


## `Observer`

### <a id="observer">Observer</a>

```java:Observer.java
public interface Observer {
	public abstract void update(NumberGenerator generator);
}
```

`Observer`のインターフェイスクラスです。実際観察するクラスはこのインターフェイスを実装します。数が生成されたタイミングで処理をするための、`update`メソッドのみになります。

## `Subject`

### <a id="number_generator">NumberGenerator</a>

```java:NumberGenerator.java
import java.util.ArrayList;
import java.util.Iterator;

public abstract class NumberGenerator {
	private ArrayList observers = new ArrayList();
	public void addObserver(Observer observer) {
		observers.add(observer);
	}
	public void deleteObserver(Observer observer) {
		observers.remove(observer);
	}
	public void notifyObservers() {
		Iterator iterator = observers.iterator();
		while (iterator.hasNext()) {
			Observer obserber = (Observer)iterator.next();
			obserber.update(this);
		}
	}
	
	public abstract int getNumber();
	public abstract void execute();
}
```

実際に数を生成するための処理`execute()`と数を取得する`getNumber()`はサブクラスに実装させる設計となっています。
ここでは観察者のインスタンスを管理するために`observers`という`ArrayList`を保持します。実際に数が生成されたタイミングで観察者に通知する場合は、`notifyObservers()`で`observers`のインスタンスに対して`update()`呼び出しています。

`Observer`のインスタンスの管理は`addObserver()`と`deleteObserver()`で行います。


## `ConcreteObserver`

### <a id="degit_observer">DegitObserver</a>

```java:DegitObserver.java
public class DegitObserver implements Observer {
	public void update(NumberGenerator generator) {
		System.out.println("DegitObserver:" + generator.getNumber());
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			
		}
	}
}
```

`Observer`の具象クラスになります。
実際に`NumberGenerator`の数が更新された際の処理を実装しています。
ここでは、単に数を出力しています。出力時に更新される様子がわかりやすいように、`Thread.sleep(100)`で処理を遅延させています。


### <a id="graph_observer">GraphObserver</a>


```java:GraphObserver.java
public class GraphObserver implements Observer {
	public void update(NumberGenerator generator) {
		System.out.print("GraphObserver:");
		int count = generator.getNumber();
		for (int i = 0; i < count; i++) {
			System.out.print("*");
		}
		System.out.println("");
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			
		}
	}
}
```

ここでは`generator`の数分記号を出力させています。


## `ConcreteSubject`

### <a id="random_number_generator">RandomNumberGenerator</a>

```java:RandomNumberGenerator.java
import java.util.Random;

public class RandomNumberGenerator extends NumberGenerator {
	private Random random = new Random();
	private int number;
	
	public int getNumber() {
		return number;
	}
	
	public void execute() {
		for (int i = 0; i < 20; i++) {
			number = random.nextInt(50);
			notifyObservers();
		}
	}
}
```

`Subject`の具象クラスです。ここでは、abstractメソッドを実装しています。
今回は簡単に乱数を発生させてnumberが更新されたタイミングで`notifyObservers()`を呼び出しています。

## 実行結果

```java
DegitObserver:20
GraphObserver:********************
DegitObserver:41
GraphObserver:*****************************************
DegitObserver:41
GraphObserver:*****************************************
DegitObserver:35
GraphObserver:***********************************
DegitObserver:16
GraphObserver:****************
DegitObserver:49
GraphObserver:*************************************************
DegitObserver:44
GraphObserver:********************************************
DegitObserver:5
GraphObserver:*****
DegitObserver:0
GraphObserver:
DegitObserver:11
GraphObserver:***********
DegitObserver:16
GraphObserver:****************
DegitObserver:43
GraphObserver:*******************************************
DegitObserver:11
GraphObserver:***********
DegitObserver:47
GraphObserver:***********************************************
DegitObserver:24
GraphObserver:************************
DegitObserver:30
GraphObserver:******************************
DegitObserver:21
GraphObserver:*********************
DegitObserver:15
GraphObserver:***************
DegitObserver:20
GraphObserver:********************
DegitObserver:46
GraphObserver:**********************************************
```

それぞれの`Observer`が数を出力できているのがわかるかと思います。


### `Subject`と`Observer`の関係性
`ConcreteSubject`は状態が変化した際に通知を行うだけで、`Observer`の具体的的なインスタンスと処理を気にする必要がありません。同様に、`ConcreteObserver`は`Subject`の具体的なインスタンスを知る必要がないです。
抽象クラスの`Subject`と`Observer`ということだけ知っておけば、通知されることと、その際に更新処理を行うことだけは担保されます。
この関係性を保って設計を行えば、具象クラスである`ConcreteSubject`と`ConcreteObserver`のクラスは***いくらでも変更が可能になります***。再利用可能な部品を扱うというデザインパターンの思想に準拠しているわけですね。
また、今回の場合は`update()`の引数として`Subject`の`NumberGenerator `インスタンスを渡していましたが、`number`のInt型を渡しても正常に動作します。値を渡す場合は、何が更新されたかの可読性は高まりますが汎用性は低下します。
一方、今回のような`NumberGenerator`のみの場合は`Subject`のインスタンスを渡さなくても大丈夫ですが、`Subject`が複数の場合は`Subject`のインスタンスを判定するために`Subject`の情報が必要になります。このようにケースによって、`update()`の簡略化や複雑化を考えて設計する必要があります。

### `Observer`の順序について
今回は更新された際、先に登録した`DegitObserver`が処理されるようになっていますが、一般的には`Observer`の`update`を呼ぶ順番が変わっても問題が起きないような設計にする必要があります。そのために、各クラスの独立性は常に保つように設計することが大切です。

#### `Observer`が`Subject`の状態を変化させる場合
今回は`Subject`自身が値を更新し、`update()`を呼び出していましたが、`update()`を呼び出すきっかけが`Observer`である場合もありえます。`GUI`における`view`操作がそれにあたる。ボタンを押した際、や画面をスワイプした際にデータを更新する場合などがそれにあたるとおもいます。この場合、`Subject`と`Observer`の設計を気をつけないと、以下のようなフローが発生する可能性があります。

1. `Subject`の状態が変化
2. `Observer`へ通知
3. `Observer`が`Subject`のメソッドを呼び出す。
4. `Subject`の状態が変化
5. `Observer`へ通知...

この場合は通知されてる最中かどうかのフラグをもたせたり、`Subject`の状態を変えないような設計にする必要があります。

### <a name="push_and_pull_type">`Push`型と`Pull`型  
通知の方法ですが、一般的に`Pull`型と`Push`型に大別されます。

- `Pull`: 状態変化時に`Observer`が`Subject`に状態を問い合わせる
- `Push`: 状態変化時に`Subject`が`Observer`に通知する

今回のサンプルケースはPush型のパターンでしたね。Push型の場合は今回のように引数が`NumberGenerator `だったように状態の変化を直接知ることができますが一般化には向いてないですね。
一方Pull型は`update()`を一般化しやすいですが、処理が複雑になりがちです。

```java:Pull型の例
public void update() {
        // Observer自身が問い合わせる
		System.out.print("Number:" + this.subject.number);
}
```


### サンプルコードについて

以下のレポジトリにソースコードをアップしてあります。

[shoheiyokoyama/design-pattern_java](https://github.com/shoheiyokoyama/design-pattern_java/tree/master/Observer)

# <a id="design_pattern">デザインパターン</a>
- 生成に関するパターン
 - Abstract factory
 - Builder
 - <a href="http://qiita.com/shoheiyokoyama/items/d752834a6a2e208b90ca" target="_blank">Factory Method</a>
 - <a href="http://qiita.com/shoheiyokoyama/items/61826e158b3c4a259065" target="_blank">Prototype</a>
 - <a href="http://qiita.com/shoheiyokoyama/items/c16fd547a77773c0ccc1" target="_blank">Singleton</a>
- 構造に関するパターン
 - <a href="http://qiita.com/shoheiyokoyama/items/bd1c692db480b640c976" target="_blank">Adapter</a>
 - Bridge
 - Composite
 - Decorator
 - Facade
 - Flyweight
 - Proxy
- 振る舞いに関するパターン 
 - Chain of responsibility
 - Command
 - Interpreter
 - <a href="http://qiita.com/shoheiyokoyama/items/3f42d0057d9d5a861039" target="_blank">Iterator</a>
 - Mediator
 - Memento
 - <a href="http://qiita.com/shoheiyokoyama/items/d4b844ed29f84a80795b" target="_blank">Observer</a>
 - State
 - Strategy
 - <a href="http://qiita.com/shoheiyokoyama/items/c2ce16b4f492cd014d50" target="_blank">Template Method</a>
 - Visitor

# 参考文献
- <a href="http://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030/ref=sr_1_1?ie=UTF8&qid=1454743284&sr=8-1&keywords=java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80" target="_blank">Java言語で学ぶデザインパターン入門</a>
- <a href="http://hamasyou.com/blog/2004/07/25/observer/" target="_blank">実践デザパタ-その14:Observerパターン</a>