元编程第一章-methods

1.介绍使用动态调用和动态定义方法来消除重复代码

2.使用Ghost Method和动态代理技术消除重复代码

 

class DS
  def initialize(id, m_info, m_price, cpu_info, cpu_price)
    @id = id
    @m_info = m_info
    @m_price = m_price
    @cpu_info = cpu_info
    @cpu_price = cpu_price
  end

  def get_mouse_info(id)
    @m_info
  end

  def get_mouse_price(id)
    @m_price
  end

  def get_cpu_info(id)
    @cpu_info
  end
  
  def get_cpu_price(id)
    @cpu_price
  end

end

 

修改了元编程书中的例子,原意是输出产品信息,价格大于100的部件,前面加上*号做标示,这些不是重点,重点是如何

通过元编程来减少代码中的重复

 

第一种方法:使用动态方法和动态派发

 

 

class Computer

  #使用白板技术(Blank State),即在代理类中删除继承来的方法
  #Computer 继承了父类Object和Kernel的一些方法
  #如果Computer调用了这些方法,是真实存在的方法,则不会进入到method_missing方法中
  instance_methods.each do |m|
    undef_method m unless m.to_s =~ /^__|method_missing|respond_to?|object_id/
  end

  def initialize(computer_id, ds)
    @id = computer_id
    @ds = ds
  end

  def method_missing(name, *args)
    super if !respond_to?(name)
      info = @ds.send "get_#{name}_info", args[0]
      price = @ds.send "get_#{name}_price", args[0]
      result = "#{name.capitalize} : #{info} ($#{price})"
      return "* #{result}" if price >100
      result
  end

  #为什么要重写respond_to?方法
  #动态生成的方法,不会出现在Object#methods中,
  #所以cmp.respond_to?(:mouse) 返回的是false,而实际上程序运行时确实是生成了mouse这个方法
  #为了解决这个问题,需要覆写respond_to?方法
  def respond_to?(method)
    @ds.respond_to?("get_#{method}_info") || super
  end

end

ds = DS.new(1, "mourse", 99, "cpu", 103)
cmp =  Computer.new(1, ds)
puts cmp.cpu
puts cmp.mouse
puts cmp.respond_to?(:mouse)

 

第二种方法:使用动态代理和白板技术

 

 

class Computer
  def initialize(computer_id, ds)
    @id = computer_id
    @ds = ds
    #Pattern Dispatch模式派发,Computer初始化的时候,获取DS的方法,解析出
    #cpu和mouse,然后通过define_componet来定义方法 cpu 和 mouse
    ds.methods.grep(/^get_(.*)_info$/){ Computer.define_component $1}
  end

  #使用define_method动态的定义方法
  def self.define_component(name)
    define_method(name) {
      info = @ds.send "get_#{name}_info", @id
      price = @ds.send "get_#{name}_price", @id
      result = "#{name.capitalize} : #{info} ($#{price})"
      return "* #{result}" if price >100
      result
    }
  end

end

#1
#puts Computer.instance_methods
#Computer不进行初始化,则没有cpu和mouse方法
#2
#ds = DS.new(1, "mourse", 99, "cpu", 103)
#cmp =  Computer.new(1, ds)
#puts Computer.instance_methods
#初始化后,Computer就产生了cpu和mouse方法

ds = DS.new(1, "mourse", 99, "cpu", 103)
cmp =  Computer.new(1, ds)
puts Computer.instance_methods
puts cmp.cpu
puts cmp.mouse
puts cmp.respond_to?(:mouse)

你可能感兴趣的:(元编程,Dynamic Methods,Pattern Dispath,Ghoset Methods,Blank State)