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];
posted @ 2012-04-12 23:48  Andy Wang  阅读(262)  评论(0)    收藏  举报