![]() |
[1999 年 7 月号] |
[Happy Squeaking!!]
それではDependencyメカニズムを利用した簡単なサンプルを作ってみましょう。
まずは、Subject側としてCoffeePotなるものを定義します。属性としてquantity(量)、temperature(温度)を持つものとします。
以下のようなクラス定義となります。
Object subclass: #CoffeePot instanceVariableNames: 'temperature quantity ' classVariableNames: '' poolDictionaries: '' category: 'Dependency tutorial'
依存物リスト(dependents)に登録された全てのDependent(Observer)に対してupdate: のメッセージを送るように実装されています。
次にアクセス用の操作を定義していきます。
状態変化のあった場合に、最後にchanged:を送るところに注目してください。
(CoffeePot >> accessingカテゴリ)
quantity ^quantity
quantity: anInteger quantity := anInteger. self changed: #quantity.
temperature ^temperature
temperature: anInteger temperature := anInteger. self changed: #temperature.
以上でCoffeePotの実装は終わりです。
次に、Dependent(Observer)側として、TemperatureAlarmを定義します。
Object subclass: #TemperatureAlarm instanceVariableNames: 'target ' classVariableNames: '' poolDictionaries: '' category: 'Dependency tutorial'
targetは温度を測る対象です。
アクセス用として以下を定義します。
(TemperatureAlarm >> accessingカテゴリ)
target ^target
target: anObject target := anObject
次は更新受け取り用の操作を定義します。
(TemperatureAlarm >> accessingカテゴリ)
update: anAspect anAspect == #temperature ifTrue: [Transcript cr; show: 'Temperature is '. Transcript show: self target temperature printString].
TemperatureAlarmは温度の変更にのみ関心があります。そこで引数anAspectとして渡されるシンボルが#temperatureの場合にのみ、トランスクリプトに温度を表示するように実装しています。
今までのソースです。
FileIn: DependencyTutorial.st (<=Click)
ではサンプルを実際に動かしてみましょう。
ワークスペースで以下を実行します。
| pot alarm | pot := CoffeePot new. alarm := TemperatureAlarm new. alarm target: pot. pot addDependent: alarm. pot quantity: 100. pot temperature: 80.
addDependent:によって、alarmをpotのObserver(Dependent)として登録しています。
変更通知メッセージ(changed:)がquantity:、temperature:の内部で共に起動されます。この際に引数anAspectにどの属性が変化したかの情報がシンボル文字列として渡されています。結果として、変更受け取り(update:)メッセージを受け取ったalarmは、温度が変化した場合にのみ反応することになります。
Transcriptには以下のように表示されます。
update:メッセージの実行結果
具象レベルではCoffeePot(Subject)はTemperatureAlarm(Observer)のことを一切知らず、抽象的な変更通知(changed:)によって変更が伝播されていくという点が重要です。
© 1999-2001 OGIS-RI Co., Ltd. |
|