вторник, 12 мая 2009 г.

12.05.09. Книга Cocoa Design Patterns. MVC, Documents, Preferences

Цели применения паттернов:
  • уменьшение связанности,
  • проектирование с учетом всевозможных изменений,
  • проектирование согласно интерфейсам, а не реализации,
  • предпочтение агрегации наследованию.

MVC (выписаны новые характеристики, которые не были отмечены в старых постах):

Контроллер конкретного приложения как правило не может быть повторно использован. Он сильно связан с представлением и моделью. Представление тяготеет с частому изменению, следовательно, нужен посредник между ним и моделью, чтобы не менять модель при каждом изменении представления. Знания, необходимые при разработке модели, существенно отличаются от знаний, необходимых при разработке графического представления.

Два примера одного калькулятора

1) без MVC

#import Cocoa/Cocoa.h
@interface PayCalculator : NSObject
{
IBOutlet NSTextField *employeeNameField;
IBOutlet NSFormCell *hourlyRateField;
IBOutlet NSFormCell *hoursWorkedField;
IBOutlet NSFormCell *standardHoursInPeriodField;
IBOutlet NSTextField *payAmountField;
IBOutlet NSButton *employeeIsExemptButton;
}
- (IBAction)calculatePayAmount:(id)sender;
@end

#import "PayCalculator.h"
@implementation PayCalculator
- (IBAction)calculatePayAmount:(id)sender
{
if(NSOnState == [employeeIsExemptButton state])
{ // Pay the hourly rate times the standard number of hours
// regardless of hours worked
[payAmountField setFloatValue:[hourlyRateField floatValue] *
[standardHoursInPeriodField floatValue]];
}
else
{ // Pay the hourly rate times the number of hour worked
float payAmount = [hourlyRateField floatValue] *
[hoursWorkedField floatValue];
if([hoursWorkedField floatValue] >
[standardHoursInPeriodField floatValue])
{ // pay 50% extra for overtime
float overtimePayAmount = 0.5f *
[hourlyRateField floatValue] *
([hoursWorkedField floatValue] -
[standardHoursInPeriodField floatValue]);
payAmount = payAmount + overtimePayAmount;
}
[payAmountField setFloatValue:payAmount];
}
}
@end

2) с MVC



@interface MYEmployee : NSManagedObject
{}
- (NSNumber *)payAmount;
@end

#import "MYEmployee.h"
@implementation MYEmployee
+ (void)initialize
{ // Configure dependant attributes
[self setKeys:[NSArray arrayWithObjects:@"isExempt",
@"hourlyRate", @"hoursWorked", @"standardHours", nil]
triggerChangeNotificationsForDependentKey:@"payAmount"];
}
- (NSNumber *)payAmount
{ // return a caculated pay amount based on other attributes
NSNumber * tmpValue;
[self willAccessValueForKey: @"payAmount"];
if([[self valueForKey:@"isExempt"] boolValue])
{ // Pay the hourly rate times the standard number of hours
// regardless of hours worked
tmpValue = [NSNumber numberWithFloat:
[[self valueForKey:@"hourlyRate"] floatValue] *
[[self valueForKey:@"standardHours"] floatValue]];
}
else
{ // Pay the hourly rate times the number of hour worked
float payAmount =
[[self valueForKey:@"hourlyRate"] floatValue] *
[[self valueForKey:@"hoursWorked"] floatValue];
if([[self valueForKey:@"hoursWorked"] floatValue] >
[[self valueForKey:@"standardHours"] floatValue])
{ // pay 50% extra for overtime
float overtimePayAmount = 0.5f *
[[self valueForKey:@"hourlyRate"] floatValue] *
([[self valueForKey:@"hoursWorked"] floatValue] -
[[self valueForKey:@"standardHours"] floatValue]);
payAmount = payAmount + overtimePayAmount;
}
tmpValue = [NSNumber numberWithFloat:payAmount];
}
[self didAccessValueForKey: @"payAmount"];
return tmpValue;
}
@end

Cocoa's Document Architecture



NSDocument - абстрактный класс, должен быть переопределен по паттерну Template Method. Должны быть переопределены критические методы:

- (BOOL)writeToURL:(NSURL *)absoluteURLofType:(NSString *)typeName error:(NSError **)outError

-(BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString*)typeName error:(NSError **)outError.

NSDocumentController является делегатом NSApplication.

При использовании Core Data есть уже готовый подкласс NSPersistentDocument класса NSDocument, который управляет объектом NSManagedObjectContext, хранящий всю нужную информацию.

Cocoa's Preference Pane Architecture

Приложение может добавить окно для своих настроек в систему System Preferences. Эта подсистема сделана по принципу MVC.

Контроллер должен быть подклассом NSPreferencePane. Ему посылается ряд сообщения при открытии окна представления, изменении настроек, закрытии окна представления и т.д.

Комментариев нет:

Отправить комментарий