代码之家  ›  专栏  ›  技术社区  ›  doodaddy

用ruby编写单例模式的正确方法是什么?

  •  26
  • doodaddy  · 技术社区  · 15 年前

    我正在尝试用ruby写一个最安全的singleton。我是新来的语言,它是如此的有弹性,我没有强烈的感觉,我的单例类将成功地创建只有一个实例。作为奖励,我希望该对象只有在真正使用时才被实例化。

    3 回复  |  直到 11 年前
        1
  •  43
  •   Dogweather    11 年前
    # 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
    

    那么当ruby在类中包含singleton模块时,它会做什么呢?

    1. 它使 new
    2. 它添加了一个名为instance的类方法,该方法只实例化类的一个实例。

    因此,要使用ruby singleton模块,需要两件事:

    1. 需要lib singleton 然后将其包含在所需的类中。
    2. 使用 instance 方法获取所需的实例。
        2
  •  17
  •   rampion    15 年前

    如果你想创建一个singleton,为什么还要创建一个类呢?只需创建一个对象,并将方法和实例变量添加到所需的对象中。

    >> 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
    

    人们实现这个模式的一个更标准的方法是使用 Module 作为singleton对象(而不是更通用的 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"
    

    如果您希望您的singleton对象从某个类继承,只需将其作为该类的实例。要从mixin继承,只需使用 #extend . 如果你想要一个单例对象,ruby让它变得非常简单,而且不像其他语言,它不必在类中定义。

    特别单件(我的第一个例子)到处都是,涵盖了我遇到的大多数情况。模块技巧通常包括其余部分(当我想要更正式的东西时)。

    ruby代码应该(imho)使用duck类型(via #respond_to? )而不是显式地检查对象的类,所以我通常不关心我的单例对象类的唯一性,因为不是它的类使它唯一,而是我在之后添加的所有内容。

        3
  •  8
  •   DigitalRoss    15 年前
    require 'singleton'
    class Klass
        include Singleton
        # ...
    end
    

    Ruby Standard Library Singleton class documention 为了一个解释。