如何在 ObjC 中创建不可变对象和 Builder 模式?

How to creating an immutable object along with a Builder pattern in ObjC?

我正在为在 ObjC 中使用构建器模式创建不可变对象而苦苦挣扎。假设我有一个具有以下属性的用户对象:

  1. 名字
  2. 姓氏

为了确保不变性,我建议使用以下代码:

@protocol User
@property (nonatomic, strong, readonly) NSString *const firstName;
@property (nonatomic, strong, readonly) NSString *const lastName;
@end

@interface User: NSObject<User>
- (instancetype)initWithFirstName:(NSString *)fName withLastName:(NSString *)lName;
@end

@implementation User
@synthesize firstName;
@synthesize lastName;

- (instancetype)initWithFirstName:(NSString *)fName withLastName:(NSString *)lName
{
    NSParameterAssert(fName);
    NSParameterAssert(lName);
    if (self = [super init]) {
        self->firstName = [fName copy];
        self->lastName = [lName copy];
    }
    return self;
}
@end

我真正苦恼的是如何为这个不可变对象实现一个生成器?

Builder 上的有用链接:

The Builder Pattern in ObjC

Builder Pattern definiton

您在上面发布的 link 使用两个对象来实现构建器模式。一个专用的构建器对象,随后传递给 create/build 方法返回要构建的对象。这是一个用不可变对象实现构建器模式的完全人为的示例。

首先让我们创建一个不可变对象;将由构建器对象构建的对象。

@interface Person: NSObject

@property (nonatomic, readonly) NSString *firstName;
@property (nonatomic, readonly) NSString *lastName;

@end

@implementation Person

- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName{

     self = [super init]
     if(!self) return nil;

     _firstName = [firstName copy];
     _lastName = [lastName copy];

     return self;

}

@end

现在让我们创建构建器对象。

@interface PersonBuilder: NSObject

@property (nonatomic, strong) NSString *firstName; 
@property (nonatomic, strong) NSString *lastName;

- (Person *)create;

@end

@implementation PersonBuilder

- (Person *)create{

     return [[Person alloc] initWithFirstName:self.firstName lastName:self.lastName];

}

@end

实施 类

PersonBuilder *builder = [PersonBuilder new];
builder.firstName = "John";
builder.lastName = "Doe";

Person *john = [builder create];

在 Objective-C 中,我真的看不出有什么好的理由来实现构建器模式,除非您试图避免冗长且令人困惑的构造函数签名,或者如果一个对象仅具有两个属性或选项,例如NSDateComponent。构建器模式本质上允许您将复杂的不可变对象的初始化拆分为多个简单的 setter 调用。在构建器上实现的 create/build 方法还为您提供了一个挂钩点,您可以在其中验证是否正在按需要创建对象。我只会在极少数情况下使用这种模式。