2009-05-11 12 views
1

私はオブジェクトのプールを管理するためのデザインパターンを探しています。私の場合、スレッドはオブジェクトを要求することができますが、リモートホストを表すオブジェクトです。デザインパターンのヘルプ:一意のオブジェクトのプール

ホストオブジェクトが存在しない場合は、作成され、プールに追加され、参照が返されます。

別のスレッドまたはオブジェクトが同じ(リモートホスト)オブジェクトを要求している場合は、それも参照を与えられます。別のリモートホストが要求された場合、そのリモートホストが作成され、オブジェクトの「プール」に追加されます。

スレッドまたはオブジェクトによってホストオブジェクトが不要になると、そのオブジェクトは自動的にプールを形成します。

  1. これにはパターンがありますか?
  2. 私はこれをObjective-Cで実装しますが、具体的なヘルプが役に立ちます。
+1

http://en.wikipedia.org/wiki/Object_pool –

答えて

5

NSMapTable(これはiPhoneなどでは使用できません)を使用する代わりに、CoreFoundationの同等機能を使用することができます。それらは通常の保持されていないポインタを含むことができます。しかし、まだリストから取り除く必要がありますが、これはオブジェクトの-deallocメソッドで簡単に行うことができます。

1つの可能性は、CFSetを使用することです。これは、あなたのオブジェクトがすべて-isEqual:-hashに正しく応答することを必要とするため、オブジェクトが既に正確に存在するかどうかをセットが判断できるようになります。例えば

(私はこれをコンパイルしていませんでしたが、それは、少なくとも90%の正解であるべきことに注意してください):

static id __uniqueObjects = nil; // GC uses NSHashTable, non-GC uses NSSet (inited using CFSet APIs) 

@interface MyHost : NSObject 
{ 
    NSURL * _hostURL; 
} 

@property (nonatomic, readonly) NSURL * hostURL; 

+ (MyHost *) uniqueHost: (MyHost *) aHost; 
+ (void) removeUniqueHost: (MyHost *) aHost;  // only used in non-GC environment 

- (id) initWithURL: (NSURL *) hostURL; 

@end 

@implementation MyHost 

- (id) initWithURL: (NSURL *) hostURL 
{ 
    self = [super init]; 
    if (self == nil) 
     return (nil); 

    // use copy, because NSURL implements NSCopying protocol 
    _hostURL = [hostURL copy]; 

    // if there's a version around already, release this instance 
    MyHost * result = [[self class] uniqueHost: self]; 
    if (result != self) 
    { 
     // set _hostURL to nil so we don't inadvertently remove anything from uniqueing table in -dealloc 
     [_hostURL release]; 
     _hostURL = nil; 
     [self release]; 
    } 

    // return either self or a pre-existing unique instance 
    return (result); 
} 

- (void) dealloc 
{ 
    // non-GC objects need to explicitly remove themselves from the uniqueing table 
    [[self class] removeUniqueHost: self]; 
    [_hostURL release]; 
    [super dealloc]; 
} 

// no need for -finalize -- under GC we use NSHashTable with weak references 

- (NSUInteger) hash 
{ 
    return ([_hostURL hash]); 
} 

- (BOOL) isEqual: (MyHost *) other 
{ 
    if (other == self) 
     return (YES); 

    return ([_hostURL isEqual: other->_hostURL]); 
} 

+ (MyHost *) uniqueHost: (MyHost *) aHost 
{ 
    if (__uniqueObjects == nil) 
    { 
     // use low-level routine to check, because iPhone has no NSGarbageCollector class 
     // we use NSHashTable or NSMutableSet, because they both respond to the same messages (NSHashTable is modeled on NSMutableSet) 
     if (objc_collectingEnabled()) 
     { 
      // hash table has zeroing weak memory, object equality (uses -isEqual:), and does NOT copy objects, just retains them 
      __uniqueObjects = [[NSHashTable hashTableWithWeakObjects] retain]; 
     } 
     else 
     { 
      CFSetCallBacks cb = { 
       0,     // version 
       NULL,    // retain (non-retaining references) 
       NULL,    // release (non-retaining references) 
       CFCopyDescription, // CF (plain C function) equivalent for -description 
       CFEqual,   // CF (plain C function) equivalent for -isEqual: 
       CFHash    // CF (plain C function) equivalent for -hash 
      } 
      __uniqueObjects = (NSMutableSet *) CFSetCreateMutable(kCFAllocatorDefault, 0, &cb); 
     } 
    } 

    MyHost * result = nil; 
    @synchronized(__uniqueObjects) 
    { 
     // treat both like an NSMutableSet & we're golden 
     // we use the -member: function to get an existing matching object from the collection 
     result = [[__uniqueObjects member: aHost] retain]; 
     if (result == nil) 
     { 
      // store & return the passed-in host object 
      [__uniqueObjects addObject: aHost]; 
      result = aHost; 
     } 
    } 

    return (result); 
} 

+ (void) removeUniqueHost: (MyHost *) aHost 
{ 
    if (__uniqueObjects == nil) 
     return;  // shouldn't ever happen, but it's a good idea to check at least 

    @synchronized(__uniqueObjects) 
    { 
     [__uniqueObjects removeObject: aHost]; 
    } 
} 

@end 

がうまくいけば、私はあなたが可能性のあるすべての質問/考えを答えるためにここに十分置かれていますこのデザインパターンについて。

0

1.簡単なものについて'Object Pool'

2. See there

+0

オブジェクトプールとは、借りて返される同種のオブジェクトの集合を意味します。これは、rjstellingの記述と同じではありません(これは、工場のようなものです)。シングルトンの場合)。 – smorgan

+0

実際には、特定のデータモデルインスタンスを参照する複数のオブジェクトが一度にメモリに常駐することを保証するために、CoreDataが使用するのと同様に、rjstellingが一意のテーブルです。 –

1

は、私が思うのに、私は、Objective-Cのdevlopperないんだけど、ここでの最善の解決策は、Multiton(それは1対1のマッピングと地図、http://en.wikipedia.org/wiki/Multiton_patternようなものだ)です。

getHost(String hostIdentifier)とreturnHost(String hostIdentifier)の2つのメソッドがあります。

すべてのホストにカウンタが必要です。 counter == 0でgetHostメソッドが呼び出された場合、必要なホストとincreseカウンタの新しいインスタンスを作成する必要があります。

counter == 1かつreturnHostが呼び出された場合は、ホストインスタンスを削除してカウンタを減らす必要があります。

また、スレッドの安全性も考慮する必要があります。

1

私は通常この種のパターンを +(id)hostWithIdentifier:(id)someIdentifierのようなもので実装します。 メソッド(既知の場合はより良い型に置き換えてください)。NSMapTableを使用して弱参照の項目を追跡します。与えられた識別子に対してインスタンスが見つからない場合は、それを割り当ててテーブルに格納します。

GCを使用していない場合は、ホストオブジェクトの-deallocメソッドでNSMapTableのエントリをクリアする必要があります。

他の人が言っているように、マルチスレッドコードの場合は注意が必要です。何らかの種類のロック機構を使用してください。

0

個々のホストオブジェクトはシングルトンパターンのようです。個々のシングルトンのコレクションを保つことができますか?

関連する問題