Observer pattern

Wzorzec obserwatora (ang. observer pattern) – wzorzec należący do grupy wzorców czynnościowych. Jest wykorzystywany w sytuacji, kiedy mamy do czynienia z pewnym modelem danych oraz kilkoma jego reprezentacjami i chcemy zachować spójność między nimi. Przykładem mogą być tu dane statystyczne oraz ich reprezentacje w postaci np. arkusza danych, wykresu słupkowego, wykresu kołowego, itp.

Przy zastosowaniu wzorca obserwatora oddzielamy logiczną strukturę danych od jej reprezentacji, unikając trwałych połączeń między klasami i umożliwiając tym samym ponowne wykorzystanie poszczególnych klas. Jednocześnie unikamy nieczytelnego i zbyt mocno rozbudowanego kodu w pojedynczej klasie.

Fragment z Wikipedii Wzorzec obserwatora

Observer pattern w Cappuccino i Objective-J

Cappuccino dostarcza framework do wysyłania wiadomości pomiędzy obiektami w procesie nazwanym „powiadomieniami”.

Obiekty zarejestrowane poprzez CPNotificationCenter będą powiadamiane gdy wysłane do nich powiadomienia CPNotifications będą spełniać pewne kryteria.

Centrum powiadomień przetwarza powiadomienia synchronicznie - czyli, zwracana jest kontrola do centrum powiadomień zaraz gdy każdy z odbiorców (obiektów obserwowanych) odbierze powiadomienie i przetworzy je.

Przykład wysyłania powiadomienia, do obiektów obserwujących, o nazwie „MySliderDidChangeValue” i obiekcie: sender (przykład z suwakami):

[[CPNotificationCenter defaultCenter] postNotificationName:@"MySliderDidChangeValue" object:sender];

Przykład rejestrowania nowych obserwujących obiektów, które będą obserwować powiadomienia o nazwie „MySliderDidChangeValue” oraz akceptować powiadomienia z dowolnego typu obiektu (object:nil).

[[CPNotificationCenter defaultCenter]
			addObserver:self
			   selector:@selector(resizeWindow:)
			       name:@"MySliderDidChangeValue"
 			     object:nil]; 	

Testowanie powiadomień w Cappuccino

Bardzo ciekawy wpis związany z testowaniem powiadomień można przeczytać na blogu Jerod Santo.

Testing Cappuccino Notifications

Kompletna aplikacja obrazująca działanie wzorca obserwator w Cappuccino

Inspiracja przykładu zaczerpnięta z: Cappuccino Casts

AppController.j
@import <Foundation/CPObject.j> 
 
@implementation AppController : CPObject 
{
	CPSlider _slider1;
	CPSlider _slider2;
}
 
- (void)applicationDidFinishLaunching:(CPNotification)aNotification 
{
	var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
		 contentView = [theWindow contentView],
		 bounds	= [contentView bounds];
 
	// Pierwszy suwak
	_slider1 = [[CPSlider alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds)/2 -300 ,100, 200,16)];
	[_slider1 setValue:200];
	[_slider1 setMinValue:50];
	[_slider1 setMaxValue:300];
	[_slider1 setTarget:self];
	[_slider1 setAction:@selector(sliderChangeValue:)];
	[contentView addSubview:_slider1];
 
	// Drugi suwak
	_slider2 = [[CPSlider alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds)/2 +10 ,100, 200,16)];
	[_slider2 setValue:200];
	[_slider2 setMinValue:50];
	[_slider2 setMaxValue:300];
	[_slider2 setTarget:self];
	[_slider2 setAction:@selector(sliderChangeValue:)];
	[contentView addSubview:_slider2];
 
	// Przyciks pierwszy
	var button1 = [[CPButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds)/2 - 300, 60, 200, 24)];
	[button1 setTitle:@"Utwórz okno 1"];
	[button1 setTarget:self];
	[button1 setAction:@selector(createNewWindowForSlider1:)]
	[contentView addSubview:button1];
 
	// Przyciks drugi
	var button2 = [[CPButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds)/2 + 10, 60, 200, 24)];
	[button2 setTitle:@"Utwórz okno 2"];
	[button2 setTarget:self];
	[button2 setAction:@selector(createNewWindowForSlider2:)]
	[contentView addSubview:button2];
 
	[theWindow orderFront:self];
}
 
// Metoda, do której jest wysyłana wiadomość podczas zmiany pozycji suwaka.
- (void)sliderChangeValue:(id)sender
{
	// Zmiana wartości suwaka powoduje nadanie powiadomienia
	// o nazwie (i identyfikatorze) "MySliderDidChangeValue"
	// Powiadomienie przesyła do obserwowanych obiekt  również obiekt suwaka
	[[CPNotificationCenter defaultCenter] postNotificationName:@"MySliderDidChangeValue" object:sender];
}
 
// Metoda, do której jest wysyłana wiadomość
// podczas kliknięcia przyciku "Utwórz okno 1"
- (void)createNewWindowForSlider1:(id)sender
{
	// Tworzenie okna powiązanego z pierwszym suwakiem
	[self createNewWindow:sender linkedToSlider:_slider1];
}
 
// Metoda, do której jest wysyłana wiadomość
// podczas kliknięcia przyciku "Utwórz okno 2"
- (void)createNewWindowForSlider2:(id)sender
{
	// Tworzenie okna powiązanego z drugim suwakiem
	[self createNewWindow:sender linkedToSlider:_slider2];
}
 
// Metoda, tworzy okno powiązane z suwakiem
- (void)createNewWindow:(id)sender linkedToSlider:(CPSlider)aSlider
{
	// wartość suwaka
	var value = [aSlider value];
	// Tworzenie instancji okna o powiązanego z suwakiem
	var window = [[MyWindow alloc] initWithContentRect:CGRectMakeZero() 
											 styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask
										linkedToSlider:aSlider];
 
	// Ustawienie położenia x,y - powiązane z wartością suwaka
	[window setFrameOrigin:CGPointMake(value,value)];
	// Wustawienie wysokości i szerokości - powiązane z wartością suwaka
	[window setFrameSize:CGSizeMake(value,value)];
 
	[window orderFront:self];
 
}
 
@end
 
 
// Własna implementacja CPWindow
// Umożliwia powiązanie okna z suwakiem poprzez dodanie go
// do obserwowanych zdarzeń o nazwie "MySliderDidChangeValue"
@implementation MyWindow : CPWindow
{
}
 
// Rozszerzenie metody "initWithContentRect:styleMask:"
- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask linkedToSlider:(CPSlider)aSlider
{
	// Inicjujemy okno
	var self = [super initWithContentRect:aContentRect styleMask:aStyleMask];
 
	if (self)
	{
		// Dodanie obiektu okna do obserwowanych powiadomień typu "MySliderDidChangeValue",
		// Obserwowany obiekt akceptuje tylko powiadomienia zawierające obiekt suwaka powiązanego z nim
		// Ustawiony jest również selektor "resizeWindow", który jest wywoływany gdy powiadomienie zostanie nadane.
		[[CPNotificationCenter defaultCenter]
			addObserver:self
			   selector:@selector(resizeWindow:)
			   	   name:@"MySliderDidChangeValue"
 			     object:aSlider]; 			     
	}
 
	return self;
}
 
// Metoda do której jest wysyłana wiadomość,
// podczas zaakceptowania wysyłanego powiadamiania "MySliderDidChangeValue"
- (void)resizeWindow:(CPNotification)aNotification
{
	var slider = [aNotification object];
	var value  = [slider value];
 
	// zmiana wielkości okna
	[self setFrameSize:CGSizeMake(value,value)];
}
 
@end;
objective-j/design-patterns/observer_pattern.txt · ostatnio zmienione: 2010/01/09 20:15 przez widmogrod
 
Wszystkie treści w tym wiki, którym nie przyporządkowano licencji, podlegają licencji: CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki