试图了解何时何地不使用单例

Tryning to understand when and when to not use a singleton

有很多关于单例的信息,什么时候使用它,为什么不应该使用它等等。所以希望能更好地理解它,也许有人可以用我正在使用的应用程序中的示例来解释它制作.

我正在使用 Parse 创建一个需要用户注册的应用程序。如果我以这种方式使用单身人士,这是好事还是坏事?我在想我将使用我的 User class 在整个应用程序中执行与用户相关的操作,也许创建 User class 的实例一次是个好主意:

//  User.h

@interface User : NSObject

+ (instancetype)sharedInstance;

- (void)createNewUser:(NSString *)username password:(NSString *)password email:(NSString*)email;

@end

// User.m

#import "User.h"
#import <Parse/Parse.h>

@implementation User

+ (instancetype)sharedInstance {
    static id sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
        NSLog(@"sharedInstance User.m");
    });

    return sharedInstance;
}

- (void)createNewUser:(NSString *)username password:(NSString *)password email:(NSString*)email {
    // Create a new user
    PFUser *newUser = [PFUser user];
    newUser.username = username;
    newUser.password = password;

    // Additional user information
    newUser[@"email"] = email;

    [newUser signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if (!error) {
            // Hooray! Let them use the app now.
            NSLog(@"Success created user: %@", newUser);
        } else {
            NSString *errorString = [error userInfo][@"error"];
            // Show the errorString somewhere and let the user try again.
            NSLog(@"Error: %@", errorString);
        }
    }];
}

@end

// LoginViewController.m

#pragma mark - IBActions

- (IBAction)loginButtonClicked:(UIButton *)sender 
{    
    [[User sharedInstance] createNewUser:self.usernameTextField.text
                                password:self.passwordTextField.text
                                   email:self.emailTextField.text];
}

或者这样做更好:

// User.h

@interface User : NSObject

- (void)createNewUser:(NSString *)username password:(NSString *)password email:(NSString*)email;

@end

// User.m

@implementation User

- (void)createNewUser:(NSString *)username password:(NSString *)password email:(NSString*)email {
    // Create a new user
    PFUser *newUser = [PFUser user];
    newUser.username = username;
    newUser.password = password;

    // Additional user information
    newUser[@"email"] = email;

    [newUser signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if (!error) {
            // Hooray! Let them use the app now.
            NSLog(@"Success created user: %@", newUser);
        } else {
            NSString *errorString = [error userInfo][@"error"];
            // Show the errorString somewhere and let the user try again.
            NSLog(@"Error: %@", errorString);
        }
    }];
}

@end

// LoginViewController.m

- (IBAction)loginButtonClicked:(UIButton *)sender
{
    User *newUser = [User new];

    [newUser createNewUser:self.usernameTextField.text
                  password:self.passwordTextField.text
                     email:self.emailTextField.text];
}

此外,如果我滥用了任何方法,请指出,感谢您的诚实!

当你想把某样东西做成单例时,这样想:

  • 这个class会真的每次申请一个永远吗? (在你的情况下,我可以看到,例如,一段时间后你会希望管理员以你的应用程序的某个用户身份登录,你最终会得到两个用户对象)
  • 这个class会不会真的永远简单到我不会遭受单例测试和全局问题(单例使单元测试变得困难,并且它们将全局实体添加到您的程序中,从而难以跟踪各个应用程序部分对其所做的更改)

如果任一选项适用于您的情况,请执行以下操作:

  • 不要让 class 成为单身人士
  • 使用依赖注入容器或注册表模式将您的 class 绑定到它,并始终根据容器/注册表
  • 解析 class