在objective-c上下文中使用工厂方法的目的是什么?

Ker*_*rog 6 objective-c factory-method

在objective-c上下文中使用工厂方法的目的是什么?

我对Objective-c中工厂方法的使用有点困惑?这样做的用处是什么?

在objective-c中使用工厂方法的示例是什么?

有点困惑.任何解释都会有帮助!

nhg*_*rif 16

Objective-C没有其他编程语言中可用的构造方法.工厂方法本质上是Objective C的构造方法.它们允许您为对象分配内存并初始化值.

在您的班级中,使用此模式添加方法:

//Please follow Obj C naming conventions and name all init 
//methods "initWith" then desc
-(id)initWithString:(NSString*)str {
    if(self = [super init]) {
        _someProperty = str;
        _someOtherProperty = 0;
    } return self;
}

//Please follow Obj C naming conventions and name all factory 
//methods "myClassWith" then desc
+(instancetype)someClassWithString:(NSString*)str {
    return [[self alloc] initWithString: str];
}

//Pretty much every factory method should have a matching init method, and 
//only one init method should actually do the if(self = [super init] { /*do
//stuff*/ } return self;, the other init methods should call this one in some
//form or fashion
Run Code Online (Sandbox Code Playgroud)

然后在main中,你可以这样做:

SomeClass *myVariableName = [SomeClass someClassWithString: 
    @"Init with me please"];
Run Code Online (Sandbox Code Playgroud)

它使您不必这样做:

SomeClass *myVariableName = [[SomeClass alloc] initWithString: 
    @"Init with me please"];
Run Code Online (Sandbox Code Playgroud)

或这个:

SomeClass *myVariableName = [[SomeClass alloc] init];
[myVariableName mySetterMethod: @"Init with me please"];
[myVariableName setThatOtherProperty: 0];
Run Code Online (Sandbox Code Playgroud)


Cou*_*per 9

工厂方法可以是返回新创建和初始化对象的任何类或实例方法.

更严格的Objective-C上下文中的"类工厂方法"是类Class的任何类方法,其名称以class开头,其前缀为stripped,第一个字母为lowercased.课程示例Foo:

+(Foo*) fooWithParam:(NSDictionary*)param;
Run Code Online (Sandbox Code Playgroud)

使用工厂方法的一个原因是为了方便.如果你有一个类,Foo它可以通常的方式创建如下:

Foo* foo = [[Foo alloc] initWithParam:param];
Run Code Online (Sandbox Code Playgroud)

现在可以使用方便的类工厂方法:

Foo* foo = [Foo fooWithParam:param];
Run Code Online (Sandbox Code Playgroud)

但是,有一个类工厂方法有用的其他原因:

例如,假设该initWithParam:方法可能失败.那么应该如何处理这个问题有很多困惑:应该在init中抛出异常吗?或者应该回归nil?关于社区中的正确方法存在争议.这两种方法都有微妙的问题,包括无法避免的内存泄漏.

因此,在这种情况下,最合理的方法是使用带有错误参数的类工厂方法.在这里,您将得到一个Foo对象,如下所示:

NSError* error;
Foo* foo = [Foo fooWithParam:param error:&error];
Run Code Online (Sandbox Code Playgroud)

现在,规则是:如果foo为nil,则出现错误,可以通过输出参数错误获取有关错误的详细信息:

if (foo) {
    ...
}
else {
    NSLog(@"Error: %@", error);
}
Run Code Online (Sandbox Code Playgroud)

通常,实现方式如下所示:

+ (Foo*) fooWithParam:(NSDictionary*)param error:(NSError**error) {
    if ([param count] < 1) {
        // invalid parameters
        if (error) {                 
            NSError* error = [NSError errorWithDomain:@"Foo" code:-1000 userInfo: ...];            
        }
        return nil;
    }
    return [[self alloc] initWithParam:param]; // won't fail
}
Run Code Online (Sandbox Code Playgroud)

另一个原因是实施"类集群".这基本上意味着类工厂方法返回类的子类.一个例子是NSStream班级.

NSInputStream班有一个类工厂方法:

+ (id)inputStreamWithFileAtPath:(NSString *)path;
Run Code Online (Sandbox Code Playgroud)

这将返回一个专门的类NSInputStream.


在ARC的前期,有一个重要的细节:

从类工厂方法返回的对象是"自动释放的".换句话说,接收对象的客户端不拥有它 - 因此不需要释放它.

如今,随着ARC,这些细节变得模糊:无论如何你都不需要手动释放这些对象.实际发布对象的方式和时间也受编译器优化的限制.

  • 您可以返回 nil 并填充传入的 NSError 指针。只是说...并且由于如前所述,Apple 确实在某些 init 方法中使用错误参数,我不明白为什么偶尔洒水也不适合您自己的代码。 (2认同)