2013-08-16 40 views
21

Vì vậy, câu hỏi khá đơn giản. Bỏ qua các tác động của việc sử dụng quá mức mẫu đơn. Tôi đang cố gắng tìm một đĩa đơn đáng tin cậy trong Objective-C. Tôi đã đi qua này:Lớp tĩnh vs Singleton

@implementation SomeSingleTonClass 

static SomeSingleTonClass* singleInstance; 

+ (SomeSingleTonClass*)getInstance 
{ 
    static dispatch_once_t dispatchOnceToken; 

    dispatch_once(&dispatchOnceToken, ^{ 
     singleInstance = [[SomeSingleTonClass alloc] init]; 
    }); 

    return singleInstance; 
} 

- (void)someMethodOnTheInstance 
{ 
    NSLog(@"DO SOMET WORK") 
} 

@end 

này tôi khá hài lòng với nhưng nó dẫn đến rất nhiều về điều này:

[[SomeSingleTonClass getInstance] someMethodOnTheInstance]; 

Câu hỏi của tôi là, tại sao điều này tốt hơn so với một lớp học hoàn toàn tĩnh.

@implementation SomeStaticClass 

static NSString* someStaticStateVariable; 

- (id)init 
{ 
    //Don't allow init to initialize any memory state 
    //Perhaps throw an exception to let some other programmer know 
    //not to do this 
    return nil; 
} 

+ (void)someStaticMethod 
{ 
    NSLog(@"Do Some Work"); 
} 

Tất cả những gì bạn thực sự đạt được là cuộc gọi phương thức tìm kiếm nhẹ nhàng hơn. Về cơ bản bạn trao đổi trên này:

[[SomeSingleTonClass getInstance] someMethodOnTheInstance]; 

Đối với điều này

[SomeStaticClass someStaticMethod]; 

Đây là một việc đơn giản hóa nhỏ chắc chắn, và bạn luôn có thể lưu trữ các ví dụ trong lớp học của bạn. Đây là sự tò mò trí tuệ hơn, những gì thần mục tiêu-C tôi pissing off bằng cách sử dụng các lớp học tĩnh thay vì singletons? Tôi chắc rằng tôi không thể là người đầu tiên nghĩ về điều này, nhưng tôi hứa, tôi đã thực hiện tìm kiếm trùng lặp trước. Vài câu trả lời tôi tìm thấy, tôi cảm thấy giống như dựa trên các phiên bản ca cao cũ hơn, bởi vì ngay cả những mẫu đơn được thảo luận dường như cũng gặp vấn đề về luồng.

+0

Tôi nghĩ bạn nói đúng, nhưng câu hỏi đó khá phức tạp (mặc dù câu trả lời là chắc chắn!). Tôi sẽ để lại cho tôi lên, nhưng đưa ra câu trả lời trong chủ đề đó, tôi không cần phải chờ đợi upvotes về câu trả lời của Drummer. Đúng. Cảm ơn! – ChrisCM

+0

Lớp tĩnh là gì? – Monolo

+0

Một lớp tĩnh (có thể là một tên tốt hơn) là một lớp dựa trên các phương thức lớp và các biến lớp tĩnh, thay vì một đối tượng instantiated và các phương thức thể hiện. Đây là những gì làm cho nó một singleton thuận tiện. Đặc biệt nếu bạn mã phương pháp init của bạn để ném một ngoại lệ! – ChrisCM

Trả lời

1

Bạn đang bực mình không có các vị thần mục tiêu-C với một lớp như thế. Trên thực tế, Apple khuyên bạn nên sử dụng mẫu đó trong một số trường hợp (tôi nghĩ họ đã đề cập đến điều này trong một trong các video phiên ARC, nơi họ thảo luận các mẫu thiết kế chung và cách triển khai chúng bằng ARC).

Trong các trường hợp khác, nơi bạn có thể có nhiều phiên bản của một lớp, nhưng muốn có một phiên bản mặc định, tất nhiên bạn sẽ phải sử dụng phương pháp thể hiện được chia sẻ.

+0

Về cơ bản chính xác. Ngoài ra, hãy xem câu trả lời trong liên kết "trùng lặp" mà Martin cung cấp cho các hậu quả của mỗi liên kết. Nó sẽ xuất hiện không phải là cách tiếp cận thực tế tốt hơn hay tệ hơn, chỉ khác nhau. – ChrisCM

+2

Một điều mà không ai chỉ ra là một singleton không tầm thường (như trái ngược với một lớp tĩnh) có thể làm nhiều thứ hơn, vì nó là một ví dụ hợp pháp. Đăng ký nhận thông báo, được quan sát giá trị khóa, được sử dụng làm nguồn dữ liệu, v.v. –

+0

Khi bạn nói "mẫu đó", bạn đang nói về mẫu hình nào? lol. Anh ta đặt hai mẫu khác nhau vào bài đăng. – TheJeff

3

Tôi thấy thuận tiện khi kết hợp cả hai. Tôi sử dụng một mô hình singleton tiêu chuẩn tương tự như đầu tiên của bạn có kết quả trong:

[[MyClass defaultInstance] doSomething]; 

Nhưng tôi cũng muốn để có thể tạo ra các trường hợp khác của cùng một lớp:

MyClass *secondInstance = [[MyClass alloc] init]; 
[secondInstance doSomething]; 

Khi tôi muốn truy cập ngắn gọn hơn để gọi các phương thức trên dụ singleton, tôi xác định phương pháp lớp học như sau:

// class method to call a method on the singleton instance 
+ (void)doSomething 
{ 
    [[MyClass defaultInstance] doSomething]; 
} 

vì vậy, với điều đó, tôi có thể sử dụng:

012.
[MyClass doSomething]; 
1

Ví dụ đầu tiên dường như không cần thiết tạo ra một thể hiện giống như một lớp đơn lẻ. Tôi nói không cần thiết bởi vì từ các bình luận khác của bạn, nó xuất hiện rằng lớp không khai báo bất kỳ thuộc tính hoặc biến cá thể nào. Cho rằng mục đích cơ bản của một đối tượng là cung cấp lưu trữ cho nhà nước, một đối tượng không có biến cá thể hiếm khi là một điều hữu ích.

Ví dụ thứ hai của bạn hiển thị một lớp không bao giờ được khởi tạo. Một lần nữa, mục đích cơ bản của một lớp trong Objective-C là hoạt động như một nhà máy cho các cá thể, vì vậy một lớp không bao giờ được khởi tạo không thực sự hữu ích hoặc cần thiết.

Thay vào đó, bạn chỉ có thể cung cấp một tập hợp các hàm C. Các hàm C không cần phải được liên kết với một lớp nào cả.Vì vậy, xem xét việc làm một cái gì đó như thế này:

static NSString* someStaticStateVariable; 

void someFunction(void) 
{ 
    NSLog(@"Do Some Work"); 
} 

Các chức năng có thể trong cặp .h/.m riêng biệt, hoặc có thể được bố trí trong .h/.m cho một lớp học hiện tại nếu nó làm cho tinh thần để làm như vậy (nói chung, nếu các hàm được liên kết chặt chẽ với các mối quan tâm của lớp đó).

+0

Các cuộc biểu tình của lớp học là để chứng minh các mẫu thiết kế mà tôi đã xem xét, chứ không phải việc sử dụng tôi đã xem xét cho chúng. Tôi tất nhiên mong đợi các lớp học của tôi có nhiều trạng thái hơn tôi đã trình bày trong các ví dụ đơn giản của tôi, vì lợi ích của câu hỏi tràn ngăn xếp. – ChrisCM

+0

@ChrisCM Bạn có vẻ đang nói rằng các cá thể của bạn sẽ có trạng thái, nhưng trong ví dụ thứ hai của bạn, bạn ghi đè 'init' để vô hiệu hóa việc tạo các cá thể, vì vậy rõ ràng không có khả năng có các đối tượng có trạng thái. Bạn không thể thêm trạng thái vào một lớp, vì vậy tất cả những gì còn lại là các biến toàn cầu. Một lần nữa, bạn không cần các lớp và các phương thức để sử dụng các biến toàn cầu, vậy tại sao không chỉ sử dụng các hàm C? – jlehr

+0

Tôi đoán cuối cùng nó không trả lời câu hỏi. Cả hai giải pháp đều phải chịu lỗ hổng tương tự, đó là lưu trữ trạng thái trong các biến toàn cầu tĩnh. Đó là "tại sao/tại sao không?" mà tôi tò mò, không phải như thế nào. Vì vậy, trong câu trả lời cho lý do tại sao không sử dụng đồng bằng chức năng C? Bởi vì, việc liên kết thứ gì đó với một lớp học vốn hữu ích để hiểu rõ hơn về mã. [MyDatabaseClass someFunction] cho tôi biết nhiều hơn về những gì đang xảy ra so với someFunction(). – ChrisCM

16

Lớp tĩnh: Được sử dụng khi bạn muốn nhóm các phương thức tiện ích theo trạng thái độc lập với nhau.

Singleton: Được sử dụng khi bạn có nhiều phương pháp chia sẻ trạng thái.

Các vấn đề liên quan