Фабрика (шаблон проектирования) в Objective C - PullRequest
26 голосов
/ 20 января 2010

Я пытаюсь создать фабрику (шаблон проектирования) в Objective C Так что я делаю что-то вроде:

+ (Car *)createCar:(int)color {
    if (color == 1) {
        return [CarFactory createBlueCar];
    } else if (color == 2) {
        return [CarFactory createRedCar];
    } else {
        return nil;
    }
}

+ (Car *)createBlueCar {
    // ...
}

+(Car*)createRedCar{
    // ...
}

Однако я не хочу, чтобы createBlueCar и createRedCar были общедоступными, и если я не определю их в файле .h, я получу предупреждение о пропущенном определении.

Я бывший Java-разработчик и новичок в Objective-C - так что это может быть просто плохой практикой. Если так, то каков будет хороший способ сделать это?

Ответы [ 3 ]

49 голосов
/ 20 января 2010

Лучший способ сделать это с расширением класса.

.h

@interface MyClass : NSObject
@property(readonly) BOOL publiclyReadOnlyPrivatelyWritableFlag;
+ (id) myExposedFactoryMethod;
@end

.m

#import "MyClass.h"

@interface MyClass ()
@property(readwrite) BOOL publiclyReadOnlyPrivatelyWritableFlag;
+ (id) privateMethod1;
+ (id) privateMEthod2;
@end

@implementation MyClass
@synthesize publiclyReadOnlyPrivatelyWritableFlag; // no ivar -- only works in 64 bit and iPhone
+ (id) myExposedFactoryMethod
{
    ...
    [self privateMethod1];
    ...
}

+ (id) privateMethod1;
{
    return ...
}

+ (id) privateMEthod2;
{
    return ...
}
@end

Расширение класса является лучшим решением, потому что оно является истинным расширением интерфейса класса, тогда как категория (без соответствующей реализации) является всего лишь предложением, чтобы класс реализовывал методы. То есть компилятор будет предупреждать, если вы не реализуете интерфейс - методы - объявленные в расширении класса, но не будет предупреждать, если вы сделали то же самое с именованной категорией.

Также обратите внимание, что расширение класса позволяет обновить свойство readonly до свойства readwrite, как показано в примере выше.

4 голосов
/ 20 января 2010

Я думаю, что вы можете добавить их в класс, используя цель-с категорией в файле реализации (не интерфейса), как способ эмуляции частных методов, если вы хотите "скрыть" их от пользователей вашего класса.

Обратите внимание: хотя вы больше не будете рекламировать методы клиентам вашего класса, они все равно смогут использовать их, если будут использовать правильные селекторы. Кроме того, они всегда могут использовать что-то вроде classdump для восстановления полного интерфейса с вашим классом, чтобы ваши методы никогда не были действительно скрыты.

См. этот вопрос для дальнейших примеров создания "приватных" методов в target-c.

0 голосов
/ 20 января 2010

Вы можете создать приватную статическую функцию

@implementation Car 

static createBlueCar () {
  ....
}

+(Car*) createCar:(int) color{
   if (color==1) {
     return createBlueCar();
   } ...
}

@end

но нет, вы не можете создать настоящего частного участника . (Вы можете использовать некоторые условные обозначения, например +(Car*)private_createCar, в частной категории, чтобы препятствовать его использованию.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...