2009-09-27 29 views
25

Tôi đang cố gắng viết một singleton an toàn nhất trong Ruby mà tôi có thể. Tôi mới đến ngôn ngữ, mà là rất đàn hồi mà tôi không có một cảm giác mạnh mẽ rằng lớp singleton của tôi sẽ thành công trong việc tạo ra chỉ có một ví dụ. Là một phần thưởng, tôi muốn đối tượng chỉ trở thành instantiated nếu thực sự được sử dụng.Cách chính xác để viết một mẫu đơn trong Ruby là gì?

Trả lời

43
# require singleton lib 
require 'singleton' 
class AppConfig 
    # mixin the singleton module 
    include Singleton 
    # do the actual app configuration 
    def load_config(file) 
    # do your work here 
    puts "Application configuration file was loaded from file: #{file}" 
    end 
end 

conf1 = AppConfig.instance 
conf1.load_config "/home/khelll/conf.yml" 
#=>Application configuration file was loaded from file: /home/khelll/conf.yml 
conf2 = AppConfig.instance 
puts conf1 == conf2 
#=>true 
# notice the following 2 lines won’t work 
AppConfig.new rescue(puts $!) 
#=> new method is private 
# dup won’t work 
conf1.dup rescue(puts $!) 
#=>private method `new’ called for AppConfig:Class 
#=>can’t dup instance of singleton AppConfig 

Vậy ruby ​​sẽ làm gì khi bạn bao gồm mô-đun đơn trong lớp học của bạn?

  1. Nó làm cho phương thức new riêng tư và do đó bạn không thể sử dụng phương thức này.
  2. Nó thêm một phương thức lớp được gọi là cá thể mà chỉ instantiates một thể hiện của lớp.

Vì vậy, để sử dụng mô-đun ruby ​​singleton bạn cần hai điều:

  1. Yêu cầu các lib singleton sau đó bao gồm nó bên trong lớp mong muốn.
  2. Sử dụng phương thức instance để lấy ví dụ bạn cần.
16

Nếu bạn muốn tạo ra một singleton, tại sao bận tâm tạo một lớp học? Chỉ cần tạo một đối tượng và thêm các phương thức và các biến mẫu vào nó mà bạn muốn.

>> MySingleton = Object.new 
=> #<Object:0x100390318> 
>> MySingleton.instance_eval do 
?> @count = 0 
>> def next 
>>  @count += 1 
>> end 
>> end 
=> nil 
>> MySingleton.next 
=> 1 
>> MySingleton.next 
=> 2 
>> MySingleton.next 
=> 3 

Một cách tiêu chuẩn hơn mà mọi người thực hiện mô hình này là sử dụng một Module như đối tượng singleton (chứ không phải chung chung hơn Object):

>> module OtherSingleton 
>> @index = -1 
>> @colors = %w{ red green blue } 
>> def self.change 
>>  @colors[(@index += 1) % @colors.size] 
>> end 
>> end 
=> nil 
>> OtherSingleton.change 
=> "red" 
>> OtherSingleton.change 
=> "green" 
>> OtherSingleton.change 
=> "blue" 
>> OtherSingleton.change 
=> "red" 

Nếu bạn muốn đối tượng singleton của bạn để kế thừa từ một số lớp, chỉ cần làm cho nó một ví dụ của lớp đó. Để kế thừa từ một mixin, chỉ cần sử dụng #extend. Nếu bạn muốn một đối tượng đơn, ruby ​​làm cho nó thực sự dễ dàng, và không giống như các ngôn ngữ khác, nó không phải được định nghĩa trong một lớp.

Mẫu đơn đặc biệt (ví dụ đầu tiên của tôi) ở khắp mọi nơi và bao gồm phần lớn các trường hợp tôi gặp phải. Các trick mô-đun thường bao gồm phần còn lại (khi tôi muốn một cái gì đó chính thức hơn một chút).

Mã Ruby nên (imho) sử dụng gõ vịt (thông qua #respond_to?) thay vì kiểm tra rõ ràng lớp của đối tượng, vì vậy tôi thường không quan tâm đến tính độc đáo của lớp đối tượng đơn của tôi, vì nó không phải là lớp của nó độc đáo, nhưng mọi thứ tôi đã thêm vào sau đó.

+6

+1 để chỉ ra rằng singleton không thực sự cần thiết. Bạn có thể thực hiện ý định mà không cần sao chép một cách lộng lẫy mẫu. –

+0

Tôi đã suy nghĩ kỹ về điểm này vì nó mang đến câu hỏi về sự tồn tại của mô-đun Singleton trong lõi ruby. Tiện ích tiềm năng của lớp w/Singleton mixin tấn công tôi gấp đôi: 1) nếu bạn muốn cả hai phương thức lớp và thể hiện và 2) nếu bạn có khởi tạo phức tạp mà bạn muốn chạy một cách lười biếng mà không yêu cầu các phương thức mô-đun bằng cách nào đó kích hoạt nó một cách rõ ràng lần đầu tiên họ được truy cập. Có ai khác có bất kỳ lợi thế của các mô-đun Singleton thực tế? – gtd

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