觀察者模式,采用氣象站的例子來說明,本質上跟Java來實現差不多。只不過是針對協議(Delegate)來編程。
簡單說下需求,氣象顯示版向氣象站注冊成功訂閱者(觀察者),氣象站監測到氣溫發生變化,向各個已注冊的氣象顯示版發出通知。
遵守針對接口編程的原則,先來寫Delegate.
第一個,需要被氣象站實現的訂閱和取消訂閱的方法。
#import "ObserverModel.h"@protocol SubjectProtocol <NSObject>- (void) registerObserver:(id<ObserverModel>) obs; - (void) removeObserver:(id<ObserverModel>) obs; - (void) notifyObservers;@end
上面被register和remove的是一個實現了ObserverModel的對象。
@protocol ObserverModel <NSObject> - (void) updateWithTemp:(float) temp withHumidity:(float)humidity withPressure:(float)pressure; @end@protocol DisplayDelegate <NSObject> - (void) display; @end
OK,下面進行氣象站的具體編碼。氣象站需要四個屬性,溫度、濕度、氣壓、訂閱者集合。
@interface WeatherData : NSObject <SubjectProtocol>{NSMutableArray * _objArray;float _tempurature;float _humidity;float _pressure; } @property (nonatomic, retain) NSMutableArray * objArray; @property (nonatomic, assign) float tempurature; @property (nonatomic, assign) float humidity; @property (nonatomic, assign) float pressure;- (id) initWithArray; - (void) registerObserver:(id<ObserverModel>)obs; - (void) removeObserver:(id<ObserverModel>)obs; - (void) notifyObservers; - (void) measurementChanged; - (void) setMeasurementsWithTemp:(float)temp withHumidity:(float)humidity withPressure:(float)pressure; @end
對應方法的實現,
@synthesize objArray = _objArray; @synthesize humidity = _humidity; @synthesize tempurature = _tempurature; @synthesize pressure = _pressure;- (id) initWithArray{self = [super init];if (self) {_objArray = [[NSMutableArray alloc] initWithCapacity:10];}return self; }- (void) registerObserver:(id<ObserverModel>)obs{[_objArray addObject:obs]; }- (void) removeObserver:(id<ObserverModel>)obs{int i = [_objArray indexOfObject:obs];if (i>=0) {[_objArray removeObjectAtIndex:i];} }- (void) notifyObservers{for (int i = 0; i < [_objArray count]; ++i) {id<ObserverModel> obj = (id<ObserverModel>)[_objArray objectAtIndex:i];[obj updateWithTemp:_tempurature withHumidity:_humidity withPressure:_pressure];} }- (void) measurementChanged{[self notifyObservers]; }- (void) setMeasurementsWithTemp:(float)temp withHumidity:(float)humidity withPressure:(float)pressure{_tempurature = temp;_humidity = humidity;_pressure = pressure;[self measurementChanged]; }
氣象顯示板的實現,初始化的時候應該把氣象站出入,使得該氣象顯示板決定是否向氣象顯示板注冊訂閱氣象。
@interface CurrentConditionsDisplay : NSObject <ObserverModel,DisplayDelegate>{float _temperature;float _humidity;id<SubjectProtocol> _weatherData; } - (void) CurrentConditionsDisplayWithObj:(id<SubjectProtocol> ) weatherData; - (void) updateWithTemp:(float)temp withHumidity:(float)humidity withPressure:(float)pressure; @end
同時,顯示板應該實現接口中的屬性更新方法和顯示方法。
- (void) CurrentConditionsDisplayWithObj:(id<SubjectProtocol> ) weatherData{_weatherData = weatherData;[weatherData registerObserver:self]; } - (void) updateWithTemp:(float)temp withHumidity:(float)humidity withPressure:(float)pressure{_temperature = temp;_humidity = humidity;[self display]; }- (void) display{NSLog(@"Temperature is %f and Humidity is %f",_temperature,_humidity); }
最后,進行整體的實例化,看看氣象站是不是能正常工作了。
WeatherData * weatherData = [[WeatherData alloc] initWithArray]; CurrentConditionsDisplay * cCD = [[CurrentConditionsDisplay alloc] init]; [cCD CurrentConditionsDisplayWithObj:weatherData]; [weatherData setMeasurementsWithTemp:20.0 withHumidity:22.0 withPressure:24.0]; [weatherData setMeasurementsWithTemp:30.0 withHumidity:32.0 withPressure:34.0];