用途区别:

delegator用于委托几乎所有方法到一个对象上,此种做法无法继承其他类
Delegator相当于一个抽象类(一般不用),它定义了子类在new时需要指定被委托对象,然后通过method_missing来委托到__getobj__上
SimpleDelegator:实现了__setobj__,用以切换被委托的对象,
DelegateClass:实现了__setobj__,用以切换被委托的对象,通过define_method来委托,会快一些

Forwardable用于委托某些方法到不同对象上,可精细地指定哪个方法去哪个对象

Delegator源码:

# 避免Object里的方法造成干扰,所以继承BasicObject
class Delegator < BasicObject

  # 但又想获取Kernel的某些方法(不想一一列出,所以用排除法undef_method)
  kernel = ::Kernel.dup
  kernel.class_eval do
    alias __raise__ raise
    # 以下方法的表现应由被委托的对象来呈现
    # 如果不去掉,那么内省、比较都会使用Delegator示例,而非被委托的对象
    [:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m|
      undef_method m
    end
   # Delegator.ancestors[1].private_instance_methods
    private_instance_methods.each do |m|
      if /\Ablock_given\?\z|iterator\?\z|\A__.*__\z/ =~ m
        next
      end
      undef_method m
    end
  end
  include kernel

  def self.const_missing(n)
    ::Object.const_get(n)
  end

  def initialize(obj)
    __setobj__(obj)
  end

  # 委托实现于此
  def method_missing(m, *args, &block)
    r = true
    target = self.__getobj__ {r = false}
    begin
      if r && target.respond_to?(m)
        target.__send__(m, *args, &block)
      elsif ::Kernel.respond_to?(m, true)
        ::Kernel.instance_method(m).bind(self).(*args, &block)
      else
        super(m, *args, &block)
      end
    ensure
      $@.delete_if {|t| %r"\A#{Regexp.quote(__FILE__)}:(?:#{[__LINE__-7, __LINE__-5, __LINE__-3].join('|')}):"o =~ t} if $@
    end
  end

  # 在Delegator上调用respond_to?时,基本上都会false,因为继承自BasicObject
  # 所以会走respond_to_missing?
  def respond_to_missing?(m, include_private)
    r = true
    target = self.__getobj__ {r = false}
    r &&= target.respond_to?(m, include_private)
    if r && include_private && !target.respond_to?(m, false)
      warn "#{caller(3)[0]}: delegator does not forward private method \##{m}"
      return false
    end
    r
  end

  # 只有methods、public_methods和protected_methods需要转发
  def methods(all=true)
    __getobj__.methods(all) | super
  end

  def public_methods(all=true)
    __getobj__.public_methods(all) | super
  end

  def protected_methods(all=true)
    __getobj__.protected_methods(all) | super
  end

  def ==(obj)
    return true if obj.equal?(self)
    self.__getobj__ == obj
  end

  def !=(obj)
    return false if obj.equal?(self)
    __getobj__ != obj
  end

  def !
    !__getobj__
  end

  # 抽象接口,需要继承重写
  def __getobj__
    __raise__ ::NotImplementedError, "need to define `__getobj__'"
  end

  # 抽象接口,需要继承重写
  def __setobj__(obj)
    __raise__ ::NotImplementedError, "need to define `__setobj__'"
  end

  #
  # Serialization support for the object returned by \_\_getobj\_\_.
  #
  def marshal_dump
    ivars = instance_variables.reject {|var| /\A@delegate_/ =~ var}
    [
      :__v2__,
      ivars, ivars.map{|var| instance_variable_get(var)},
      __getobj__
    ]
  end

  #
  # Reinitializes delegation from a serialized object.
  #
  def marshal_load(data)
    version, vars, values, obj = data
    if version == :__v2__
      vars.each_with_index{|var, i| instance_variable_set(var, values[i])}
      __setobj__(obj)
    else
      __setobj__(data)
    end
  end

  def initialize_clone(obj) # :nodoc:
    self.__setobj__(obj.__getobj__.clone)
  end
  def initialize_dup(obj) # :nodoc:
    self.__setobj__(obj.__getobj__.dup)
  end
  private :initialize_clone, :initialize_dup

  # 此4个方法是Object才有
  # 当然,即使BasicObject有,也应pass给被委托对象
  [:trust, :untrust, :taint, :untaint, :freeze].each do |method|
    define_method method do
      __getobj__.send(method)
      super()
    end
  end

  # 只是alias
  @delegator_api = self.public_instance_methods
  def self.public_api
    @delegator_api
  end
end

# SimpleDelegator只是实现了Delegator的get/set
#
# 用法举例:
#
# 1. 桥接/适配,满足调用者的接口
#
#   class User
#     def born_on
#       Date.new(1989, 9, 10)
#     end
#   end
#
#   class UserDecorator < SimpleDelegator
#     def birth_year
#       born_on.year
#     end
#   end
#
#   decorated_user = UserDecorator.new(User.new)
#   decorated_user.birth_year  #=> 1989
#   decorated_user.__getobj__  #=> #<user: ...="">
#
# 2. 拦截/装饰。重写接口,
#    当调用super时,因SimpleDelegator无该方法
#    会进入method_missing,即交由被委托对象来处理
#
#   class SuperArray < SimpleDelegator
#     def [](*args)
#       super + 1
#     end
#   end
#
#   SuperArray.new([1])[0]  #=> 2
#
class SimpleDelegator<delegator  ="" #="" block可以是某些容错或其它回调触发机制=""  ="" #="" 如delegator#method_missing的{r="false}"  ="" def="" __getobj__=""  =""  ="" unless="" defined?(@delegate_sd_obj)=""  =""  =""  ="" return="" yield="" if="" block_given?=""  =""  =""  ="" __raise__="" ::argumenterror,="" "not="" delegated"=""  =""  ="" end=""  =""  ="" @delegate_sd_obj=""  ="" end=""  ="" #="" 切换被委托的对象,新对象与旧对象应有相同接口=""  ="" def="" __setobj__(obj)=""  =""  ="" __raise__="" ::argumenterror,="" "cannot="" delegate="" to="" self"="" if="" self.equal?(obj)=""  =""  ="" @delegate_sd_obj="obj"  ="" end="" end="" def="" delegator.delegating_block(mid)="" #="" :nodoc:=""  ="" lambda="" do="" |*args,="" &block|=""  =""  ="" target="self.__getobj__"  =""  ="" begin=""  =""  =""  ="" target.__send__(mid,="" *args,="" &block)=""  =""  ="" ensure=""  =""  =""  ="" $@.delete_if="" {|t|="" \a#{regexp.quote(__file__)}:#{__line__-2}:="" o="~" t}="" if="" $@=""  =""  ="" end=""  ="" end="" end="" #="" 返回一个继承delegator的class(这样initialize时,会__setobj__,保存被委托的对象)="" #="" 并且该class拥有superclass的所有“领域接口”(使得定义该class子类时,可定义一些adapter接口)="" #="" 例如:="" #="" # =""  class="" q="" <="" delegateclass(array)="" #="" step="" 1="" # =""  =""  def="" enq="" obj="" #=""  =""  =""   __getobj__="" <<="" obj="" # =""  =""  end="" #=""  =""  ="" def="" deq="" #=""  =""  =""  ="" _getobj__.shift="" #=""  =""  =""  end="" # =""  end="" #="" #=""  ="" q="Q.new" [1,2,3]="" #=""  ="" q.enq="" 4="" #="" 1,2,3,4="" #=""  ="" q.deq="" #="" 2,3,4="" #="" def="" delegateclass(superclass)=""  ="" klass="Class.new(Delegator)"  ="" methods="superclass.instance_methods"  ="" methods="" -="::Delegator.public_api"  ="" methods="" -="[:to_s,:inspect,:=~,:!~,:===]"  ="" klass.module_eval="" do=""  =""  ="" def="" __getobj__ ="" #="" :nodoc:=""  =""  =""  ="" unless="" defined?(@delegate_dc_obj)=""  =""  =""  =""  ="" return="" yield="" if="" block_given?=""  =""  =""  =""  ="" __raise__="" ::argumenterror,="" "not="" delegated"=""  =""  =""  ="" end=""  =""  =""  ="" @delegate_dc_obj=""  =""  ="" end=""  =""  ="" def="" __setobj__(obj) ="" #="" :nodoc:=""  =""  =""  ="" __raise__="" ::argumenterror,="" "cannot="" delegate="" to="" self"="" if="" self.equal?(obj)=""  =""  =""  ="" @delegate_dc_obj="obj"  =""  ="" end=""  =""  ="" methods.each="" do="" |method|=""  =""  =""  ="" define_method(method,="" delegator.delegating_block(method))=""  =""  ="" end=""  ="" end=""  ="" klass.define_singleton_method="" :public_instance_methods="" do="" |all="true|"  =""  ="" super(all)="" -="" superclass.protected_instance_methods=""  ="" end=""  ="" klass.define_singleton_method="" :protected_instance_methods="" do="" |all="true|"  =""  ="" super(all)="" |="" superclass.protected_instance_methods=""  ="" end=""  ="" return="" klass="" end<="" code=""></delegator></user:>


Forwardable源码:

# 假设类RecordCollection的对象含有数组@records
# 那么你可以用def_delegator
# 将record_number()指向@records的的[],如下:
#
#   require 'forwardable'
#
#   class RecordCollection
#     attr_accessor :records
#     extend Forwardable
#     def_delegator :@records, :[], :record_number
#   end
#
# 使用时:
#
#   r = RecordCollection.new
#   r.records = [4,5,6]
#   r.record_number(0)  # => 4
#
# 如果不是方法改名,而只是简单委派,用def_delegators :
#
#   class RecordCollection # re-open RecordCollection class
#     def_delegators :@records, :size, :<<, :map
#   end
#
#   r = RecordCollection.new
#   r.records = [1,2,3]
#   r.record_number(0)   # => 1
#   r.size               # => 3
#   r << 4               # => [1, 2, 3, 4]
#   r.map { |x| x * 2 }  # => [2, 4, 6, 8]
#
# 甚至可以针对单个对象来定义委派:
# (使用def_delegator但不需改方法名时,可不指定)
#
#   my_hash = Hash.new
#   my_hash.extend Forwardable              # prepare object for delegation
#   my_hash.def_delegator "STDOUT", "puts"  # add delegation for STDOUT.puts()
#   my_hash.puts "Howdy!"
#
# 相比继承,使用组合与委派能更精细的控制对象能响应哪些方法:
#
#   class Queue
#     extend Forwardable
#
#     def initialize
#       @q = [ ]    # prepare delegate object
#     end
#
#     # setup preferred interface, enq() and deq()...
#     def_delegator :@q, :push, :enq
#     def_delegator :@q, :shift, :deq
#
#     # support some general Array methods that fit Queues well
#     def_delegators :@q, :clear, :first, :push, :shift, :size
#   end
#
#   q = Queue.new
#   q.enq 1, 2, 3, 4, 5
#   q.push 6
#
#   q.shift    # => 1
#   while q.size > 0
#     puts q.deq
#   end
#
#   q.enq "Ruby", "Perl", "Python"
#   puts q.first
#   q.clear
#   puts q.first
#
# This should output:
#
#   2
#   3
#   4
#   5
#   6
#   Ruby
#   nil
#
# == Notes
#
# Be advised, RDoc will not detect delegated methods.
#
# +forwardable.rb+ provides single-method delegation via the def_delegator and
# def_delegators methods. For full-class delegation via DelegateClass, see
# +delegate.rb+.
#
module Forwardable
  # Version of +forwardable.rb+
  FORWARDABLE_VERSION = "1.1.0"

  FILE_REGEXP = %r"#{Regexp.quote(__FILE__)}"

  # 设了debug的话,才保留报错栈中的本程序信息
  @debug = nil
  class << self
    # If true, __FILE__ will remain in the backtrace in the event an
    # Exception is raised.
    attr_accessor :debug
  end

  # delegate method => accessor
  # delegate [method, method, ...] => accessor
  # 参数为一hash,key是(一组)方法名的symbol,value是被委托对象
  def instance_delegate(hash)
    hash.each{ |methods, accessor|
      methods = [methods] unless methods.respond_to?(:each)
      methods.each{ |method|
        def_instance_delegator(accessor, method)
      }
    }
  end

  # 一次过定义多个转发方法,但不能指定新方法名
  # 排除重定义__send__和__id__
  # 但其实还是可以通过def_instance_delegator和instance_delegate
  # 不过eval的时候会警告
  def def_instance_delegators(accessor, *methods)
    methods.delete("__send__")
    methods.delete("__id__")
    for method in methods
      def_instance_delegator(accessor, method)
    end
  end

  # 直接掉调此方法来定义的话,可指定新接口
  #
  #   class MyQueue
  #     extend Forwardable
  #     attr_reader :queue
  #     def initialize
  #       @queue = []
  #     end
  #
  #     def_delegator :@queue, :push, :mypush
  #   end
  #
  #   q = MyQueue.new
  #   q.mypush 42
  #   q.queue    #=> [42]
  #   q.push 23  #=> NoMethodError
  #
  def def_instance_delegator(accessor, method, ali = method)
    line_no = __LINE__; str = %{
      def #{ali}(*args, &block)
        begin
          #{accessor}.__send__(:#{method}, *args, &block)
        rescue Exception
          # 将报错栈中有关本文件的行去掉,使报错更清晰
          $@.delete_if{|s| Forwardable::FILE_REGEXP =~ s} unless Forwardable::debug
          ::Kernel::raise
        end
      end
    }
    # 如果是class或module,则直接定义实例方法,否则,定义一般对象的单例方法
    # 这意味着,并不一定要让实例去extend SingleForwardable来获得单例特有的转发机制
    begin
      module_eval(str, __FILE__, line_no)
    rescue
      instance_eval(str, __FILE__, line_no)
    end

  end

  alias delegate instance_delegate
  alias def_delegators def_instance_delegators
  alias def_delegator def_instance_delegator
end

# 通过extend SingleForwardable,使对象(非class)获得其单例特有的转发机制
#
# 一般用法就是把方法转发给实例变量,但是转给全局对象也可以
# 如下,使printer的puts方法引用STDOUT的puts:
#
#    printer = String.new
#    printer.extend SingleForwardable        # prepare object for delegation
#    printer.def_delegator "STDOUT", "puts"  # add delegation for STDOUT.puts()
#    printer.puts "Howdy!"
#
# 同理,以下Implementation和Facade位于同一层次
# 可用SingleForwardable使Facade的service方法引用Implementation的service
# 这用Forwardable是做不到的(因为Forwardable优先module_eval,定义实例方法)
#
#   class Implementation
#     def self.service
#       puts "serviced!"
#     end
#   end
#
#   module Facade
#     extend SingleForwardable
#     def_delegator :Implementation, :service
#   end
#
#   Facade.service #=> serviced!
#
# If you want to use both Forwardable and SingleForwardable, you can
# use methods def_instance_delegator and def_single_delegator, etc.
module SingleForwardable
  def single_delegate(hash)
    hash.each{ |methods, accessor|
      methods = [methods] unless methods.respond_to?(:each)
      methods.each{ |method|
        def_single_delegator(accessor, method)
      }
    }
  end

  def def_single_delegators(accessor, *methods)
    methods.delete("__send__")
    methods.delete("__id__")
    for method in methods
      def_single_delegator(accessor, method)
    end
  end

  def def_single_delegator(accessor, method, ali = method)
    str = %{
      def #{ali}(*args, &block)
        begin
          #{accessor}.__send__(:#{method}, *args, &block)
        rescue Exception
          $@.delete_if{|s| Forwardable::FILE_REGEXP =~ s} unless Forwardable::debug
          ::Kernel::raise
        end
      end
    }

    # 直接instance_eval定义单例方法
    instance_eval(str, __FILE__, __LINE__)
  end

  alias delegate single_delegate
  alias def_delegators def_single_delegators
  alias def_delegator def_single_delegator
end