Obj-C 实现设计模式 -- Observer
观察者模式,采用气象站的例子来说明,本质上跟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];

浙公网安备 33010602011771号