Observer パターン(オブザーバ・パターン) とは、プログラム内のオブジェクトのイベント( 事象 )を他のオブジェクトへ通知する処理で使われるデザインパターンの一種。
通知するオブジェクト側が、通知されるオブジェクト側に観察(英: observe)される形になる事から、こう呼ばれる。
出版-購読型モデルとも呼ばれる。暗黙的呼び出しの原則と関係が深い。
分散イベント処理システムの実装にも使われる。言語によっては、このパターンで扱われる問題は言語が持つイベント処理構文で処理される。
Java で Observer パターン
import java.util.ArrayList;
interface Observer {
public void update(float interest);
}
interface Subject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}
class Loan implements Subject {
private ArrayList<Observer> observers = new ArrayList<Observer>();
private String type;
private float interest;
private String bank;
public Loan(String type, float interest, String bank) {
this.type = type;
this.interest = interest;
this.bank = bank;
}
public float getInterest() {
return interest;
}
public void setInterest(float interest) {
this.interest = interest;
notifyObservers();
}
public String getBank() {
return this.bank;
}
public String getType() {
return this.type;
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer ob : observers) {
System.out.println("Notifying Observers on change in Loan interest rate");
ob.update(this.interest);
}
}
}
class Newspaper implements Observer {
@Override
public void update(float interest) {
System.out.println("Newspaper: Interest Rate updated, new Rate is: " + interest);
}
}
class Internet implements Observer {
@Override
public void update(float interest) {
System.out.println("Internet: Interest Rate updated, new Rate is: "
+ interest);
}
}
public class ObserverTest {
public static void main(String args[]) {
// this will maintain all loans information
Newspaper printMedia = new Newspaper();
Internet onlineMedia = new Internet();
Loan personalLoan = new Loan("Personal Loan", 12.5f,
"Standard Charterd");
personalLoan.registerObserver(printMedia);
personalLoan.registerObserver(onlineMedia);
personalLoan.setInterest(3.5f);
}
}
PHP で Observer パターン
<?php
abstract class AbstractObserver {
abstract function update(AbstractSubject $subject_in);
}
abstract class AbstractSubject {
abstract function attach(AbstractObserver $observer_in);
abstract function detach(AbstractObserver $observer_in);
abstract function notify();
}
function writeln($line_in) {
echo $line_in."<br/>";
}
class PatternObserver extends AbstractObserver {
public function __construct() {
}
public function update(AbstractSubject $subject) {
writeln('*IN PATTERN OBSERVER - NEW PATTERN GOSSIP ALERT*');
writeln(' new favorite patterns: '.$subject->getFavorites());
writeln('*IN PATTERN OBSERVER - PATTERN GOSSIP ALERT OVER*');
}
}
class PatternSubject extends AbstractSubject {
private $favoritePatterns = NULL;
private $observers = array();
function __construct() {
}
function attach(AbstractObserver $observer_in) {
//could also use array_push($this->observers, $observer_in);
$this->observers[] = $observer_in;
}
function detach(AbstractObserver $observer_in) {
//$key = array_search($observer_in, $this->observers);
foreach($this->observers as $okey => $oval) {
if ($oval == $observer_in) {
unset($this->observers[$okey]);
}
}
}
function notify() {
foreach($this->observers as $obs) {
$obs->update($this);
}
}
function updateFavorites($newFavorites) {
$this->favorites = $newFavorites;
$this->notify();
}
function getFavorites() {
return $this->favorites;
}
}
writeln('BEGIN TESTING OBSERVER PATTERN');
writeln('');
$patternGossiper = new PatternSubject();
$patternGossipFan = new PatternObserver();
$patternGossiper->attach($patternGossipFan);
$patternGossiper->updateFavorites('abstract factory, decorator, visitor');
$patternGossiper->updateFavorites('abstract factory, observer, decorator');
$patternGossiper->detach($patternGossipFan);
$patternGossiper->updateFavorites('abstract factory, observer, paisley');
writeln('END TESTING OBSERVER PATTERN');
?>
出力結果
BEGIN TESTING OBSERVER PATTERN
*IN PATTERN OBSERVER - NEW PATTERN GOSSIP ALERT*
new favorite patterns: abstract factory, decorator, visitor
*IN PATTERN OBSERVER - PATTERN GOSSIP ALERT OVER*
*IN PATTERN OBSERVER - NEW PATTERN GOSSIP ALERT*
new favorite patterns: abstract factory, observer, decorator
*IN PATTERN OBSERVER - PATTERN GOSSIP ALERT OVER*
END TESTING OBSERVER PATTERN
Python で Observer パターン
"""
Define a one-to-many dependency between objects so that when one object
changes state, all its dependents are notified and updatedautomatically.
"""
import abc
class Subject:
"""
Know its observers. Any number of Observer objects may observe a
subject.
Send a notification to its observers when its state changes.
"""
def __init__(self):
self._observers = set()
self._subject_state = None
def attach(self, observer):
observer._subject = self
self._observers.add(observer)
def detach(self, observer):
observer._subject = None
self._observers.discard(observer)
def _notify(self):
for observer in self._observers:
observer.update(self._subject_state)
@property
def subject_state(self):
return self._subject_state
@subject_state.setter
def subject_state(self, arg):
self._subject_state = arg
self._notify()
class Observer(metaclass=abc.ABCMeta):
"""
Define an updating interface for objects that should be notified of
changes in a subject.
"""
def __init__(self):
self._subject = None
self._observer_state = None
@abc.abstractmethod
def update(self, arg):
pass
class ConcreteObserver(Observer):
"""
Implement the Observer updating interface to keep its state
consistent with the subject's.
Store state that should stay consistent with the subject's.
"""
def update(self, arg):
self._observer_state = arg
# ...
def main():
subject = Subject()
concrete_observer = ConcreteObserver()
subject.attach(concrete_observer)
subject.subject_state = 123
if __name__ == "__main__":
main()