Observerパターン
状態が変化したことを他のオブジェクトに通知する
Observer とは、英語で「観察者」を意味する単語です。Observer パターンとは、状態の変化を観察することを目的としたものですが、どちらかというと「観察」よりも「通知」に重点の置かれたものになっています。
あるインスタンスの状態が変化した際に、そのインスタンス自身が、「観察者」に状態の変化を「通知」する仕組みです。例えば、ビラ配りのアルバイトをしている学生について考えて見ましょう。アルバイトの学生がビラ配りが終わったことを伝える必要に駆られた場合、広告会社の担当者に連絡して終了したことを伝えます。アルバイトの学生を管理しているのは「広告会社」で、終了を伝えるのは「アルバイトの学生」です。「アルバイトの学生」は、アルバイトを止めたくなったり、まだ続けたかったりしたら「広告会社」に連絡します。ごく当たり前のことですが、このような仕組みによって、広告会社は全てのアルバイトの学生を常に観察する必要からのがれられるのです。
このように、状態が変化する方が「通知」をする仕組みを持つことで、観察者は常に観察しなければいけない状態から開放されます。Mediator パターンの一部でもこのような仕組みは利用されています。
Observer パターンは、このような通知の仕組みをより汎用的に利用できる形で提供するためのパターンです。
Java では、Observer パターンのクラスがライブラリとして提供されており、Observer には java.util.Observer 、 通知する側 には java.util.Observable を利用することができます。
しかし、 java.util.Observer で渡すインスタンスは、java.util.Observable のサブクラスである必要があります。よって、観察される側のクラスがすでに他のクラスを継承している場合には使えないことになります。
先に紹介した、Mediatorパターンとは、どちらも「状態変化を通知する」という点では似ています。しかし、パターンの目的や視点は異なります。Mediatorパターンの場合の状態変化の通知は、他のオブジェクトの調停という目的で動いているMediatorパターンの一部の機能に過ぎません。Observer パターンでは、他のオブジェクトの状態変化を Observer(複数かもしれない)に通知すること、通知して同期を取ることに主眼があります。
例題
不定期に、0から100までの数値を発生するクラスがあります。
そのクラスから10回数値を取り表示しなさい。
|
Observer パターンではないとき ..........................15 ....................72 .........................100 .............................92 ...........................76 ......................................63 ..............................36 ...............................11 ....................................76 ......................23 |
Observer パターンのとき 55 95 90 28 25 10 17 34 41 95 |
共通クラス
|
Observerパターンを使用しない例 Observer.java public class Observer extends Thread {
RandomNumberGenerator nm;
public Observer(RandomNumberGenerator nm) {
this.nm = nm;
}
public void run() {
for (int i= 0; i < 10; i++) {
int n = -1;
while (n < 0) {
try {
Thread.sleep(100); // 0.1秒ごと
}
catch (InterruptedException e) { }
yield();
n = nm.getNumber();
System.out.print(".");
}
System.out.println(n);
}
}
}
Main.java public class Main {
public static void main(String[] args) {
RandomNumberGenerator nm = new RandomNumberGenerator();
nm.start();
Observer observer = new Observer(nm);
observer.start();
}
}
|
Observerパターンを使用した例 NewRandomNumberGenerator.java public class NewRandomNumberGenerator extends RandomNumberGenerator {
private Observer observer;
public void addObserver(Observer observer) {
this.observer = observer;
}
public int getNumber() { return number; }
public void run() {
for (int i = 0 ; i < 10 ; i++) {
generate();
observer.update(this);
}
}
}
Observer.java public class Observer {
public void update(NewRandomNumberGenerator generator) {
System.out.println(generator.getNumber());
}
}
Main.java public class Main {
public static void main(String[] args) {
NewRandomNumberGenerator generator = new NewRandomNumberGenerator();
Observer observer = new Observer();
generator.addObserver(observer);
generator.start();
}
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 observer.h #include <windows.h>
#include <process.h>
#include "randomNumberGenerator.h"
class observer
{
private:
bool status = true;
randomNumberGenerator* nm;
static unsigned __stdcall run_(void*);
public:
observer(void);
observer(randomNumberGenerator*);
virtual ~observer(void);
void run(void);
bool getStatus(void);
}; observer.cpp using namespace std;
#include "observer.h"
observer::observer(void) {}
observer::observer(randomNumberGenerator* nm) : nm(nm) {
// thisポインタをreinterpret_castしてrun_に渡す
_beginthreadex(0, 0, run_, (void*)this, 0, 0);
}
observer::~observer(void) {}
void observer::run() {
for (int i = 0 ; i < 10 ; i++) {
int n = -1;
while (n < 0) {
Sleep(100); // 0.1 秒ごと
n = nm->getNumber();
cout << ".";
}
cout << n << endl;
}
}
unsigned __stdcall observer::run_(void* that) {
// ポインタを戻す
observer* me = (observer*)that;
me->run();
me->status = false;
_endthreadex(0);
return 0;
}
bool observer::getStatus(void) {
return status;
} main.cpp #include <windows.h>
#include "randomNumberGenerator.h"
#include "observer.h"
int main() {
randomNumberGenerator generator;
generator.start();
observer observer(&generator);
while(true) {
Sleep(1000);
if (observer.getStatus() == false) break;
}
return 0;
}
|
Observerパターンを使用した例 newRandomNumberGenerator.h #include "observer.h"
#include "randomNumberGenerator.h"
class newRandomNumberGenerator : public randomNumberGenerator
{
private:
observer* obsr;
bool status;
static unsigned __stdcall run_(void*);
public:
newRandomNumberGenerator(void);
virtual ~newRandomNumberGenerator(void);
void addObserver(observer*);
void run(void);
void start(void);
bool getStatus(void);
}; newRandomNumberGenerator.cpp #include <windows.h>
#include <process.h>
#include "newRandomNumberGenerator.h"
newRandomNumberGenerator::newRandomNumberGenerator(void) {}
newRandomNumberGenerator::~newRandomNumberGenerator(void) {}
void newRandomNumberGenerator::addObserver(observer* ob) {
this->obsr = ob;
}
void newRandomNumberGenerator::run(void) {
for (int i = 0 ; i < 10 ; i++) {
generate();
obsr->update(*this);
}
status = false;
}
void newRandomNumberGenerator::start(void) {
// thisポインタをreinterpret_castしてrun_に渡す
_beginthreadex(0, 0, run_, (void*)this, 0, 0);
}
unsigned __stdcall newRandomNumberGenerator::run_(void* that) {
// ポインタを戻す
randomNumberGenerator* me = (randomNumberGenerator*)that;
me->run();
_endthreadex(0);
return 0;
}
bool newRandomNumberGenerator::getStatus(void) {
return status;
} observer.h class newRandomNumberGenerator;
class observer
{
private:
bool status;
public:
observer(void);
virtual ~observer(void);
void update(newRandomNumberGenerator&);
};
observer.cpp #include <iostream>
using namespace std;
#include "observer.h"
#include "newRandomNumberGenerator.h"
observer::observer(void) {}
observer::~observer(void) {}
void observer::update(newRandomNumberGenerator& generator) {
cout << generator.getNumber() << endl;
}
main.cpp #include <windows.h>
#include "newRandomNumberGenerator.h"
#include "observer.h"
int main() {
newRandomNumberGenerator generator;
observer ob;
generator.addObserver(&ob);
generator.start();
while(true) {
Sleep(1000);
if (generator.getStatus() == false) break;
}
return 0;
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ(NewRandomNumberGenerator#run 内の generate の後の update)呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.cs class Observer
{
RandomNumberGenerator generator;
public Observer(RandomNumberGenerator generator)
{
this.generator = generator;
}
public void Run()
{
for (int i = 0; i < 10; i++)
{
int n = -1;
while(n < 0)
{
System.Threading.Thread.Sleep(100); // 0.1秒
n = generator.GetNumber();
Console.Write("."); // データがない
}
Console.WriteLine(n); // 取得したデータを表示
}
}
}
Program.cs class Program
{
static void Main(string[] args)
{
RandomNumberGenerator generator = new RandomNumberGenerator();
Thread tg = new Thread(new ThreadStart(g.Run));
Observer observer = new Observer(generator);
Thread tob = new Thread(new ThreadStart(observer.Run));
tg.Start(); // スレッド開始
tob.Start();
tg.Join(); // スレッドの終了を待つ
tob.Join();
}
}
|
Observerパターンを使用した例 NewRandomNumberGenerator.cs class NewRandomNumberGenerator : RandomNumberGenerator
{
private Observer observer;
public void AddObserver(Observer observer)
{
this.observer = observer;
}
public new int GetNumber()
{
return number;
}
public new void Run()
{
for (int i = 0; i < 10; i++)
{
Generate();
observer.Update(this);
}
}
}
Observer.cs class Observer
{
public void Update(NewRandomNumberGenerator generator)
{
// 取得したデータを表示
Console.WriteLine(generator.GetNumber());
}
}
Program.cs class Program
{
static void Main(string[] args)
{
NewRandomNumberGenerator generator = new NewRandomNumberGenerator();
Thread thread = new Thread(new ThreadStart(generator.Run));
Observer observer = new Observer();
generator.AddObserver(observer);
thread.Start(); // スレッド開始
}
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ(NewRandomNumberGenerator#Run 内の Generate の後の Update)呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では Update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.vb Public Class Observer
Dim generator As RandomNumberGenerator
Public Sub New(ByVal generator As RandomNumberGenerator)
Me.generator = generator
End Sub
Public Sub Run()
For i As Integer = 0 To 9
Dim n As Integer = -1
While (n < 0)
System.Threading.Thread.Sleep(100) ' 0.1秒
n = generator.getNumber()
Console.Write(".") ' データがない
End While
Console.WriteLine(n) ' 取得したデータを表示
Next
End Sub
End Class
Program.vb Module Main
Sub Main()
Dim generator As RandomNumberGenerator = New RandomNumberGenerator()
Dim tg As Thread = New Thread(AddressOf generator.run)
Dim observer As Observer = New Observer(generator)
Dim tob As Thread = New Thread(AddressOf observer.run)
tob.Start() ' スレッド開始
tg.Start()
tg.Join() ' スレッドの終了を待つ
tob.Join()
End Sub
End Module
|
Observerパターンを使用した例 NewRandomNumberGenerator.vb Public Class NewRandomNumberGenerator
Inherits RandomNumberGenerator
Private observer As Observer
Public Sub AddObserver(observer As Observer)
Me.observer = observer
End Sub
Public Overloads Function GetNumber() As Integer
Return number
End Function
Public Overloads Sub Run()
For i As Integer = 0 To 9
Generate()
observer.Update(Me)
Next
End Sub
End Class
Observer.vb Public Class Observer
Public Sub update(ByVal generator As RandomNumberGenerator)
' 取得したデータを表示
Console.WriteLine(generator.GetNumber())
End Sub
End Class
Program.vb Imports System.Threading
Module Main
Sub Main()
Dim generator As NewRandomNumberGenerator = New NewRandomNumberGenerator()
Dim t As Thread = New Thread(AddressOf generator.Run)
Dim observer As Observer = New Observer()
generator.AddObserver(observer)
t.Start() ' スレッド開始
t.Join() ' スレッドの終了を待つ
End Sub
End Module
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.js module.exports = class Observer {
constructor(nm) {
this.nm = nm;
}
async start() {
for (let i = 0; i < 10; i++) {
let n = -1;
while (n < 0) {
await sleep(100); // 0.1秒ごと
n = this.nm.getNumber();
process.stdout.write(".");
}
process.stdout.write(n + "\n");
}
}
}
function sleep(msec) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, msec);
});
}
Main.js const RandomNumberGenerator = require("./RandomNumberGenerator.js");
const Observer = require("./Observer.js");
let nm = new RandomNumberGenerator();
nm.start();
let observer = new Observer(nm);
observer.start();
|
Observerパターンを使用した例 NewRandomNumberGenerator.js const RandomNumberGenerator = require("./RandomNumberGenerator.js");
module.exports = class NewRandomNumberGenerator
extends RandomNumberGenerator {
addObserver(observer) {
this.observer = observer;
}
getNumber() { return this.number; }
async start() {
for (let i = 0 ; i < 10 ; i++) {
await this.generate();
this.observer.update(this);
}
}
}
Observer.js module.exports = class Observer {
update(generator) {
process.stdout.write(generator.getNumber() + "\n");
}
}
Main.java const NewRandomNumberGenerator = require("./NewRandomNumberGenerator.js");
const Observer = require("./Observer.js");
let generator = new NewRandomNumberGenerator();
let observer = new Observer();
generator.addObserver(observer);
generator.start();
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ(NewRandomNumberGenerator#start 内の generate の後の update)呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.pm $| = 1;
package Observer {
use Time::HiRes 'usleep';
sub new {
my ($class, $nm) = @_;
my $this = { nm => $nm };
return bless $this, $class;
}
sub start {
my ($this) = @_;
for ( 0..9 ) {
my $n = -1;
while ($n < 0) {
usleep(100 * 1000); # 0.1秒ごと
$n = $this->{nm}->getNumber();
print ".";
}
print $n . "\n";
}
}
}
1;
Main.pl use lib qw(./);
use RandomNumberGenerator;
use Observer;
use threads;
my $nm = new RandomNumberGenerator();
my $t = threads->create(\&startGenerator, $nm);
my $observer = new Observer($nm);
$observer->start();
$$t->join();
sub startGenerator {
my ($nm) = @_;
$nm->start();
}
|
Observerパターンを使用した例 NewRandomNumberGenerator.pm package NewRandomNumberGenerator {
use base qw(RandomNumberGenerator);
use threads;
use threads::shared;
sub new {
my ($class) = @_;
my $this = {};
return bless $this, $class;
}
sub addObserver {
my ($this, $observer) = @_;
$this->{observer} = $observer;
}
sub getNumber {
my ($this) = @_;
return $this->SUPER::getNumber();
}
sub start {
my ($this) = @_;
for ( 0..9 ) {
$this->generate();
$this->{observer}->update($this);
}
}
}
1;
Observer.pm $| = 1;
package Observer {
sub new {
my ($class) = @_;
return bless {}, $class;
}
sub update {
my ($this, $generator) = @_;
print $generator->getNumber() . "\n";
}
}
1;
Main.pl use lib qw(./);
use NewRandomNumberGenerator;
use Observer;
use threads;
use threads::shared;
my $generator = new NewRandomNumberGenerator();
my $observer = new Observer();
$generator->addObserver($observer);
my $t = threads->create(\&startGenerator, $generator);
$t->join();
sub startGenerator {
my ($generator) = @_;
$generator->start();
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ(NewRandomNumberGenerator#start 内の generate の後の update)呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.rb class Observer
def initialize(nm)
@nm = nm
end
def start()
i = 0
loop do
n = -1
while n < 0
sleep(0.1) # 0.1秒ごと
n = @nm.getNumber()
print "."
end
puts n
i += 1
break if i >= 10
end
end
end
Main.rb require './RandomNumberGenerator'
require './Observer'
nm = RandomNumberGenerator.new()
block = Thread.new do
nm.start()
end
observer = Observer.new(nm)
observer.start()
|
Observerパターンを使用した例 NewRandomNumberGenerator.rb require './RandomNumberGenerator'
class NewRandomNumberGenerator < RandomNumberGenerator
def addObserver(observer) {
@observer = observer
end
def getNumber()
return @number
end
def start()
for i in 0..9 do
generate()
@observer.update(self)
end
end
end
Observer.rb class Observer
def update(generator) {
puts generator.getNumber()
end
end
Main.rb require './NewRandomNumberGenerator'
require './Observer'
generator = NewRandomNumberGenerator.new()
observer = Observer.new()
generator.addObserver(observer)
generator.start()
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ(NewRandomNumberGenerator#start 内の generate の後の update)呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.py import threading
from time import sleep
class Observer(threading.Thread):
def __init__(self, nm):
super(Observer, self).__init__()
self.nm = nm
def run(self):
for i in range(10):
n = -1
while (n < 0:
sleep(0.1) # 0.1秒ごと
n = self.nm.getNumber()
print(".", end="", flush=True)
print(n, flush=True)
Main.pv from RandomNumberGenerator import RandomNumberGenerator
from Observer import Observer
nm = RandomNumberGenerator()
nm.start()
observer = Observer(nm)
observer.start()
|
Observerパターンを使用した例 NewRandomNumberGenerator.pv from RandomNumberGenerator import RandomNumberGenerator
from Observer import Observer
class NewRandomNumberGenerator(RandomNumberGenerator):
def addObserver(self, observer):
self.observer = observer
def getNumber(self):
return self.number
def run(self):
for i in range(10):
self.generate()
self.observer.update(self)
Observer.pv class Observer:
def update(self, generator):
print(generator.getNumber())
Main.py from NewRandomNumberGenerator import NewRandomNumberGenerator
from Observer import Observer
generator = NewRandomNumberGenerator()
observer = Observer()
generator.addObserver(observer)
generator.start()
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.php <?php
class Observer extends Thread {
private $nm;
public function __construct($nm) {
$this->nm = $nm;
}
public function run() {
for ($i= 0; $i < 10; $i++) {
$n = -1;
while ($n < 0) {
time_nanosleep(0, 100 * 1000 * 1000); // 0.1秒ごと
$n = $nm->getNumber();
print ".";
}
print "$n\n";
}
}
}
?>
Main.php require_once('RandomNumberGenerator.php');
require_once('Observer.php');
$nm = new RandomNumberGenerator();
$nm->start();
$observer = new Observer($nm);
observer->start();
|
Observerパターンを使用した例 NewRandomNumberGenerator.php <?php
require_once('RandomNumberGenerator.php');
class NewRandomNumberGenerator extends RandomNumberGenerator {
public function addObserver($observer) {
$this->observer = $observer;
}
public function getNumber() { // 数を取得する
return $this->number;
}
public function run() {
for ($i = 0 ; $i < 10 ; $i++) {
$this->generate();
$this->observer->update($this);
}
}
}
?>
Observer.php <?php
class Observer {
public function update($generator) {
print $generator->getNumber() . "\n";
}
}
?>
Main.php <?php
require_once('NewRandomNumberGenerator.php');
require_once('Observer.php');
$generator = new NewRandomNumberGenerator();
$observer = new Observer();
$generator->addObserver($observer);
$generator->start();
?>
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.ts import {RandomNumberGenerator} from "./RandomNumberGenerator";
export
class Observer {
private nm:RandomNumberGenerator;
public constructor(nm:RandomNumberGenerator) {
this.nm = nm;
}
public async start() {
for (let i:number = 0; i < 10; i++) {
let n:number = -1;
while (n < 0) {
await sleep(100); // 0.1秒ごと
n = this.nm.getNumber();
process.stdout.write(".");
}
process.stdout.write(n + "\n");
}
}
}
function sleep(msec:number) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, msec);
});
}
Main.ts import {RandomNumberGenerator} from "./RandomNumberGenerator";
import {Observer} from "./Observer";
let nm:RandomNumberGenerator = new RandomNumberGenerator();
nm.start();
let observer:Observer = new Observer(nm);
observer.start();
|
Observerパターンを使用した例 NewRandomNumberGenerator.ts import {RandomNumberGenerator} from "./RandomNumberGenerator";
import {Observer} from "./Observer";
export
class NewRandomNumberGenerator extends RandomNumberGenerator {
private observer:Observer;
public addObserver(observer:Observer):void {
this.observer = observer;
}
public getNumber():number {
return number;
}
public async start():Promise<void> {
for (let i:number = 0 ; i < 10 ; i++) {
await this.generate();
this.observer.update(this);
}
}
}
Observer.ts import {NewRandomNumberGenerator} from "./NewRandomNumberGenerator";
export
class Observer {
public update(generator:NewRandomNumberGenerator):void {
process.stdout.write(generator.getNumber() + "\n");
}
}
Main.ts import {NewRandomNumberGenerator} from "./NewRandomNumberGenerator";
import {Observer} from "./Observer";
let generator:NewRandomNumberGenerator = new NewRandomNumberGenerator();
let observer:Observer = new Observer();
generator.addObserver(observer);
generator.start();
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.swift import Foundation
public class Observer {
private var nm:RandomNumberGenerator
public init(nm:RandomNumberGenerator) {
self.nm = nm;
}
public func start() {
for _ in 0..<10 {
var n:Int = -1
while n < 0 {
Thread.sleep(forTimeInterval: 0.1) // 0.1秒ごと
n = nm.getNumber()
print(".", terminator:"")
fflush(stdout)
}
print(n)
}
}
}
Main.swift import Foundation
let dispatchGroup:DispatchGroup = DispatchGroup()
let dispatchQueue:DispatchQueue = DispatchQueue(label: "queue", attributes: .concurrent)
dispatchGroup.enter()
let nm:RandomNumberGenerator = RandomNumberGenerator()
dispatchQueue.async {
nm.start()
}
let observer:Observer = Observer(nm)
observer.start()
dispatchGroup.leave()
|
Observerパターンを使用した例 NewRandomNumberGenerator.swift public class NewRandomNumberGenerator : RandomNumberGenerator {
private var observer:Observer!
public func addObserver(_ observer:Observer) {
self.observer = observer
}
public override func getNumber() -> Int {
return number
}
public override func start() {
for _ in 0..<10 {
self.generate()
observer.update(self)
}
}
}
Observer.swift import Foundation
public class Observer {
public func update(_ generator:NewRandomNumberGenerator) {
print(generator.getNumber())
}
}
Main.java import Foundation
let generator:NewRandomNumberGenerator = NewRandomNumberGenerator()
let observer:Observer = Observer()
generator.addObserver(observer)
generator.start()
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.kt class Observer(private val nm: RandomNumberGenerator) : Thread() {
override fun run() {
for (i in 0..9) {
var n: Int = -1
while (n < 0) {
sleep(100) // 0.1秒ごと
n = nm.getNumber()
print(".")
}
println(n)
}
}
}
Main.kt fun main() {
val nm = RandomNumberGenerator()
nm.start()
val observer = Observer(nm)
observer.start()
}
|
Observerパターンを使用した例 NewRandomNumberGenerator.kt class NewRandomNumberGenerator : RandomNumberGenerator {
private lateinit var observer: Observer
fun addObserver(observer: Observer) {
this.observer = observer
}
override fun getNumber(): Int {
return number
}
override fun run() {
for (i in 0..9) {
generate()
observer.update(this)
}
}
}
Observer.kt class Observer {
fun update(generator: NewRandomNumberGenerator) {
println(generator.getNumber())
}
}
Main.kt fun main() {
val generator = NewRandomNumberGenerator()
val observer = Observer()
generator.addObserver(observer)
generator.start()
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.scala class Observer(val nm: RandomNumberGenerator) extends Thread {
override def run() {
for (i <- 0 until 10) {
var n: Int = -1
while (n < 0) {
Thread.sleep(100) // 0.1秒ごと
n = nm.getNumber()
System.out.print(".")
}
System.out.println(n)
}
}
}
Main.scala object Main {
def main(args: Array[String]) {
val nm = new RandomNumberGenerator()
nm.start()
val observer = new Observer(nm)
observer.start()
}
}
|
Observerパターンを使用した例 NewRandomNumberGenerator.scala class NewRandomNumberGenerator extends RandomNumberGenerator {
private var observer: Observer = null
def addObserver(observer: Observer) {
this.observer = observer
}
override def getNumber(): Int = number
override def run() {
for (_ <- 0 until 10) {
generate()
observer.update(this)
}
}
}
Observer.scala class Observer {
def update(generator: NewRandomNumberGenerator) {
System.out.println(generator.getNumber())
}
}
Main.scala object Main {
def main(args: Array[String]) {
val generator = new NewRandomNumberGenerator()
val observer = new Observer()
generator.addObserver(observer)
generator.start()
}
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.groovy class Observer extends Thread {
RandomNumberGenerator nm
Observer(RandomNumberGenerator nm) {
this.nm = nm
}
void run() {
for (int i in 0..<10) {
int n = -1
while (n < 0) {
try {
Thread.sleep(100) // 0.1秒ごと
}
catch (InterruptedException e) { }
yield()
n = nm.getNumber()
System.out.print(".")
}
System.out.println(n)
}
}
} Main.groovy class Main {
static void main(String[] args) {
RandomNumberGenerator nm = new RandomNumberGenerator()
nm.start()
Observer observer = new Observer(nm)
observer.start()
}
}
|
Observerパターンを使用した例 NewRandomNumberGenerator.groovy public class NewRandomNumberGenerator extends RandomNumberGenerator {
private Observer observer
void addObserver(Observer observer) {
this.observer = observer
}
int getNumber() { return number }
void run() {
for (int i in 0..<10) {
generate()
observer.update(this)
}
}
}
Observer.groovy class Observer {
void update(NewRandomNumberGenerator generator) {
System.out.println(generator.getNumber())
}
} Main.groovy class Main {
static void main(String[] args) {
NewRandomNumberGenerator generator = new NewRandomNumberGenerator()
Observer observer = new Observer()
generator.addObserver(observer)
generator.start()
}
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.go import (
"fmt"
"time"
)
type Observer struct {
nm *RandomNumberGenerator
}
func (self *Observer) Run() {
for i:=0; i<10; i++ {
var n = -1
for n < 0 {
time.Sleep(time.Millisecond * 100) // 0.1秒ごと
n = self.nm.GetNumber()
fmt.Print(".")
}
fmt.Println(n)
}
}
func NewObserver(nm *RandomNumberGenerator) *Observer {
return &Observer {
nm: nm,
}
}
Main.go func main() {
var nm = NewRandomNumberGenerator()
go nm.Run()
var observer = NewObserver(nm)
observer.Run()
}
|
Observerパターンを使用した例 NewRandomNumberGenerator.go type NewRandomNumberGenerator struct {
RandomNumberGenerator
observer *Observer
}
func (self *NewStyleRandomNumberGenerator) AddObserver(observer *Observer) {
self.observer = observer
}
func (self *NewStyleRandomNumberGenerator) GetNumber() int {
return self.number
}
func (self *NewStyleRandomNumberGenerator) Run() {
for i:=0 i<10; i++ {
self.generate()
self.observer.Update(self)
}
}
func NewNewStyleRandomNumberGenerator() *NewStyleRandomNumberGenerator {
return &NewStyleRandomNumberGenerator{}
}
Observer.go import "fmt"
type Observer struct {}
func (self *Observer) Update(generator *NewRandomNumberGenerator) {
fmt.Println(generator.GetNumber())
}
func NewObserver() *Observer {
return &Observer {}
}
Main.go func main {
var generator = NewNewRandomNumberGenerator()
var observer = NewObserver()
generator.AddObserver(observer)
generator.Run()
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では Update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 observer.d import std.stdio;
import core.thread;
import randomnumbergenerator;
public class Observer : Thread {
RandomNumberGenerator nm;
public this(RandomNumberGenerator nm) {
this.nm = nm;
super(&run);
}
public void run() {
foreach (int i; 0..10) {
int n = -1;
while (n < 0) {
Thread.sleep(dur!("msecs")(100)); // 100ミリ秒ごと
yield();
n = nm.getNumber();
write(".");
}
writeln(n);
}
}
}
main.d import randomnumbergenerator;
import observer;
int main() {
RandomNumberGenerator nm = new RandomNumberGenerator();
nm.start();
Observer observer = new Observer(nm);
observer.start();
return 0;
}
|
Observerパターンを使用した例 newRandomnumbergenerator.d import randomnumbergenerator;
import observer;
public class NewRandomNumberGenerator : RandomNumberGenerator {
private Observer observer;
public void addObserver(Observer observer) {
this.observer = observer;
}
public override int getNumber() { return number; }
public override void run() {
foreach (int i; 0..10) {
generate();
observer.update(this);
}
}
}
observer.d import std.stdio;
import newrandomnumbergenerator;
public class Observer {
public void update(NewRandomNumberGenerator generator) {
writeln(generator.getNumber());
}
}
main.d import newrandomnumbergenerator;
import observer;
int main() {
NewRandomNumberGenerator generator = new NewRandomNumberGenerator();
Observer observer = new Observer();
generator.addObserver(observer);
generator.start();
return 0;
}
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |
共通クラス
|
Observerパターンを使用しない例 Observer.pas unit UnitObserver;
interface
uses
System.Classes,
UnitRandomNumberGenerator;
type
Observer = class
private
var nm:RandomNumberGenerator;
public
constructor Create(nm:RandomNumberGenerator);
procedure run();
end;
implementation
constructor Observer.Create(nm:RandomNumberGenerator);
begin
self.nm := nm;
end;
procedure Observer.run();
var i, n:integer;
begin
for i := 0 to 9 do begin
n := -1;
while n < 0 do begin
TThread.Sleep(100); // 0.1秒ごと
n := nm.getNumber();
Write('.');
end;
Writeln(n);
end;
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitRandomNumberGenerator,
UnitObserver;
var nm:RandomNumberGenerator;
var _observer:Observer;
begin
nm := RandomNumberGenerator.Create();
_observer := Observer.Create(nm);
_observer.run();
nm.Free();
_observer.Free();
end.
|
Observerパターンを使用した例 NewRandomNumberGenerator.pas unit UnitNewRandomNumberGenerator;
interface
uses
UnitRandomNumberGenerator;
type
NewRandomNumberGenerator = class(RandomNumberGenerator)
public
procedure addObserver(obs:TObject); // 循環参照を避ける
function getNumber():integer;
procedure run();
end;
implementation
uses
UnitObserver;
var _observer:Observer;
procedure NewRandomNumberGenerator.addObserver(obs:TObject);
begin
_observer := (obs as Observer); // 循環参照を避ける
end;
function NewRandomNumberGenerator.getNumber():integer;
begin
Result := number;
end;
procedure NewRandomNumberGenerator.run();
var i:integer;
begin
for i := 0 to 9 do begin
generate();
_observer.update(self);
end;
end;
end.
Observer.pas unit UnitObserver;
interface
uses
UnitNewRandomNumberGenerator;
type
Observer = class
public
procedure update(generator:NewRandomNumberGenerator);
end;
implementation
procedure Observer.update(generator:NewRandomNumberGenerator);
begin
Writeln(generator.getNumber());
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitNewRandomNumberGenerator,
UnitObserver;
var generator:NewRandomNumberGenerator;
var _observer:Observer;
begin
generator := NewRandomNumberGenerator.Create();
_observer := Observer.Create();
generator.addObserver(_observer);
generator.run();
generator.Free();
_observer.Free();
end.
|
|
値は不定期に発生しますから、データが発生していないかどうか、常に確認に行かなければなりません。 しかし、取りに行ってもまだ数値がないこともあるし、取りに行く前に次の数値が発生してしまっているかもしれません。 この例では、0.1秒ごとデータを確認に行き、値が負ならまだ発生していないということなので、また0.1秒待ってデータを確認しに行きます。 |
Observer パターンでは、データが発生したときだけ呼び出され、データを取りにいっています。 データ発生元は、もちろんデータが発生したかどうかが分かるわけですから、そのタイミングで Observer のメソッド(この例では update)を呼び出しています。 |