@interface MySingleton: NSObject + (MySingleton *)setup:(MyConfig *)config; + (MySingleton *)shared; @property (readonly,strong,nonatomic) MyConfig *config; @end @implementation MySingleton static MySingleton *sharedInstance = nil; + (MySingleton *)setup:(MyConfig *)config { static dispatch_once_t onceToken; dispatch_once(&onceToken,^{ sharedInstance = [[self alloc] initWithConfig:config]; }); // Some other stuff here return sharedInstance; } + (MySingleton *)shared { if (sharedInstance == nil) { NSLog(@"error: shared called before setup"); } return sharedInstance; } - (instancetype)initWithConfig:(RVConfig *)config { self = [super init]; if (self) { _config = config; } return self; } @end
我被困在Swift:
class Asteroid { var config: ASTConfig? // This actually should be read-only class func setup(config: ASTConfig) -> Asteroid { struct Static { static let instance : Asteroid = Asteroid(config: config) } return Static.instance } class var shared: Asteroid? { // ??? } private init(config: ASTConfig) { self.config = config } }
private var _asteroidSharedInstance: Asteroid! class Asteroid { private var config: ASTConfig? class func setup(config: ASTConfig) -> Asteroid { struct Static { static var onceToken: dispatch_once_t = 0 } dispatch_once(&Static.onceToken) { _asteroidSharedInstance = Asteroid(config: config) } return _asteroidSharedInstance } class var sharedInstance: Asteroid! { // personally,I'd make this `Asteroid`,not `Asteroid!`,but this is up to you if _asteroidSharedInstance == nil { println("error: shared called before setup") } return _asteroidSharedInstance } init(config: ASTConfig) { self.config = config } }
或者,在Swift 1.2中,您可以消除静态结构并简化安装程序:
private static var setupOnceToken: dispatch_once_t = 0 class func setup(config: ASTConfig) -> Asteroid { dispatch_once(&setupOnceToken) { _asteroidSharedInstance = Asteroid(config: config) } return _asteroidSharedInstance }
这真的不是一个单身人士. (我怀疑你知道这一点,但我提到为了未来读者的利益).通常单例可以在首次使用的任何地方进行实例化.这是一个场景,它只在一个特定的地方进行实例化和配置,您必须注意在尝试在其他地方使用它.这是非常好奇的做法.我们失去了一些单例功能,但仍然遭受所有传统的单身限制.
很明显,如果你确定,那没关系.但是,如果你有趣的替代品,两个人就跳出来:
>使这个真正的单例:您可以通过在init方法中移动ASTConfig的实例化来实现此目的(消除在使用sharedInstance之前必须调用setup的依赖关系).然后你可以退出设置,只要像你一样使用你的单身.所产生的实现也大大简化.它减少到像:
class Asteroid { static let sharedInstance = Asteroid() private let config: ASTConfig init() { self.config = ASTConfig(...) } }
显然,我怀疑恶魔是在这个ASTConfig对象的细节,但是如果你可以做一个正确的单例执行,你可以看到这是更简单(特别是在Swift 1.2).而且上面消除了设置vs sharedInstance问题.消除私人全球.一切都简单一些
话虽如此,我认为你有令人信服的理由这样做.也许有一些关键原因,您必须将ASTConfig对象传递给安装方法,而不是仅在Asteroid类的初始化中实例化.
我只是觉得有必要指出,一个适当的单例将是非常好的(两者都更简单的实现和消除理论竞争条件).
>完全放弃单例模式:假设使用一个合适的单身,如上所述,下一个问题是你是否应该放弃任何剩余的单身,只是实例化一个简单的小行星,你正在调用设置,然后而不是依赖sharedInstance,只是传递给真正需要它的对象.
您已经指定您要手动将Asteroid设置在前面,所以让我们正式确定这种关系,并消除单身人士介绍的许多结构性缺陷(参见What’s Alternative to Singleton或谷歌“单身人士”).
不要误会我我假设你有令人信服的理由按照你的方式做到这一点,如果目前的实现方式适用于你,那没关系.但这是一个非常好奇的做法,在这种做法中,您不用享受所有的好处就承担单身人士的理论责任.