objective-c - Objective-C 中的优雅和 'correct' multiton 实现?

标签 objective-c design-patterns singleton multiton

您认为这种在 objective-c 中实现的 multiton 是“优雅的”吗?我以编程方式“禁止”使用 allocallocWithZone:,因为分配或不分配内存的决定需要根据键来完成。

我确定我只需要处理两个实例,所以我使用“switch-case”而不是 map 。

#import "Multiton.h"

static Multiton *firstInstance = nil;
static Multiton *secondInstance = nil;

@implementation Multiton

+ (Multiton *) sharedInstanceForDirection:(enum KeyName)direction {

    return [[self allocWithKey:direction] init];
}

+ (id) allocWithKey:(enum KeyName)key {

    return [self allocWithZone:nil andKey:key];
}

+ (id) allocWithZone:(NSZone *)zone andKey:(enum KeyName)key {

    Multiton **sharedInstance;

    @synchronized(self) {

        switch (key) {
            case KEY_1:
                sharedInstance = &firstInstance;
                break;
            case KEY_2:
                sharedInstance = &secondInstance;
                break;
            default:
                [NSException raise:NSInvalidArgumentException format:@"Invalid key"];
                break;
        }
        if (*sharedInstance == nil)
            *sharedInstance = [super allocWithZone:zone];
    }

    return *sharedInstance;
}

+ (id) allocWithZone:(NSZone *)zone {

    //Do not allow use of alloc and allocWithZone
    [NSException raise:NSObjectInaccessibleException format:@"Use allocWithZone:andKey: or allocWithKey:"];
    return nil;
}

- (id) copyWithZone:(NSZone *)zone {

    return self;
}

- (id) retain {

    return self;
}

- (unsigned) retainCount {

    return NSUIntegerMax;
}

- (void) release {

    return;
}

- (id) autorelease {

    return self;
}

- (id) init {
    [super init];
    return self;
}

@end

PS:我还没有尝试过这是否有效,但它的编译很干净:)

最佳答案

我发现单例是个坏主意,这看起来可怕四倍。代码非常复杂,您肯定会花几个小时来寻找其中的细微错误,您可能永远不会对它感到满意。那可不行。您应该抛开这种可憎的做法,并以其他不需要太多思考的方式将您的对象连接在一起。

如果您喜欢模式,您可以使用类似于工厂模式的东西来连接您的对象。工厂将负责创建这两​​个实例并将它们传递到任何需要的地方。而且工厂将比 Multiton 简单得多:

@interface Factory : NSObject {
    Foo *foo1, *foo2;
}
@end

@implementation Factory

- (id) init {
    [super init];
    foo1 = [[Foo alloc] init];
    foo2 = [[Foo alloc] init];
    return self;
}

当然,您不必同时创建两个实例。你可以在那里做任何你喜欢的事情——缓存、延迟加载,任何事情。重点是将 Foo 生命周期管理留给工厂,与 Foo 代码分开。然后它变得容易得多。 ¶ 所有其他需要 Foo 的对象都将通过 Factory 创建和连接,并将通过 setter 接收它们的 Foo:

@implementation Factory

- (id) wireSomeClass {
    id instance = [[SomeClass alloc] init];
    [instance setFoo:foo1];
    [instance setAnotherDependency:bar];
    return [instance autorelease];
}

这比您问题中的代码要简单得多。

关于objective-c - Objective-C 中的优雅和 'correct' multiton 实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2507312/

相关文章:

java - Java中的单例和继承

ios - Swift Obj-c 模型

iphone - 键盘隐藏时的iOS事件

c# - 在 C# 中使用 IDisposable 的模板方法模式

c# - C++ 和 C# 中的复合模式 - protected 虚拟方法

java - 如何在 Selenium Grid 上对两个单例浏览器进行多线程处理?

java - 如果在经典单例模式(如果有的话)中使用最终实例有什么好处呢?

ios - 禁用自动布局本地化行为(RTL - 从右到左行为)

ios - 如何使用代码将 UITableView 放在 UILabel 下方

java - 当组合需要访问封闭类时进行建模?