【问题标题】:Tryning to understand when and when to not use a singleton试图了解何时以及何时不使用单例
【发布时间】:2015-04-26 04:42:36
【问题描述】:

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

我正在使用 Parse 创建一个带有用户注册的应用。如果我以这种方式使用单例,这是好的还是坏的做法?我想我将使用我的User 类在整个应用程序中与用户相关的操作,也许创建一次User 类的实例是个好主意:

//  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];
}

另外,如果我误用了任何方式,请直说,感谢您的诚实!

【问题讨论】:

  • > “我将使用我的用户类来做很多不同的事情” - 让类做很多不同的事情是一种不好的做法。检查“单一责任”原则。
  • 也许那一点有点不清楚,将我的问题的那部分更新为:“我想我将使用我的用户类来用户相关操作”@Avt

标签: ios singleton


【解决方案1】:

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

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

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

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

【讨论】:

  • 谢谢@FractalizeR 现在开始有点清晰了。因此,在我的 User 类案例中,将 User 设为单例并不是一个好主意,但也许将一个名为 UserManager 的类设为可能具有 getUserId 和 displayUserName 等方法的单例,或者我想错了?您是否还有一个简单的示例来说明何时以及何时不使用单例?
  • @Oskariagon 我认为重命名一个类是错误的,让他的职责留在原地;)如果你愿意,UserManager 可以创建用户实例。我没有看到你的架构,我无法提出足够明智的建议;)
  • @Oskariagon 欢迎 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 2020-08-10
  • 2012-05-13
  • 1970-01-01
  • 2019-12-15
相关资源
最近更新 更多