ruby元编程之杂记2
Posted
一个重复代码的问,题虽然重复就是一切.但是你知道的。 重复1
class DS
def initialize
def get_mouse_info(workstation_id)
def get_mouse_price(workstation_id)
def get_cpu_info(workstation_id)
def get_cpu_price(workstation_id)
def get_display_info(workstation_id)
def get_display_price(workstation_id)
end
ds = DS.new
ds.get_mouse_info(42)
ds.get_mouse_price(42)
ds.get_cpu_info(42)
ds.get_cpu_price(42)
ds.get_display_info(42)
ds.get_display_price(42)
这样的代码,会发现人生的重点都是“command+c”与“command+v”,在无乐趣可言。
class Computer
def initialize(computer_id,data_source)
@id = computer_id
@data_source = data_source
end
def mouse
info = @data_source.get_mouse_info(@id)
price = @data_source.get_mouse_price(@id)
result = "Mouse: #{info} ($#{price})"
return " * #{result} " if price >=100
result
end
def cpu
info = @data_source.get_cpu_info(@id)
price = @data_source.get_cpu_price(@id)
result = "cpu: #{info} ($#{price})"
return " * #{result} " if price >=100
result
end
def keyboard
info = @data_source.get_keyboard_info(@id)
price = @data_source.get_keyboard_price(@id)
result = "keyboard: #{info} ($#{price})"
return " * #{result} " if price >=100
result
end
… ...
end
dynamic_call.rb(动态调用方法)
class MyClass
def my_method(my_arg)
my_arg * 2
end
end
obj = Myclass.new
obj.my_method(3)
obj.send(:my_method,3)
dynamic_defintion(动态定方法)
class MyClass
define_method :my_method do |my_arg|
my_arg * 3
end
end
obj = MyClass.new
obj.my_method(2)
重构Computer类 第一步:添加动态派发
class Computer
def initialize(computer_id,data_source)
@id = computer_id
@data_source = data_source
end
def mouse
component :mouse
end
def cpu
component :cpu
end
def keyboard
component :keyboard
end
def component
info = @data_source.send "get_#{name}_info", @id
price = @data_source.send "get_#{name}_price", @id
result= "#{name.to_s.capitalize}: #{info} ($#{price})"
return " * #{result}" if price >=100
result
end
end
my_computer = Computer.new(42,DS.new)
my_computer.cpu => * Cpu: 2.16 Ghz ($220)
第二步:动态创建方法
class Computer
def initialize(computer_id,data_source)
@id = computer_id
@data_source = data_source
end
def self.define_component(name)
define_method(name){
info = @data_source.send "get_#{name}_info", @id
price = @data_source.send "get_#{name}_price", @id
result= "#{name.to_s.capitalize}: #{info} ($#{price})"
return " * #{result}" if price >=100
result
}
end
define_component :mouse
define_component :cpu
define_component :keyboard
end
第三步:用内省(Introspection)方式缩减代码
class Computer
def initialize(computer_id,data_source)
@id = computer_id
@data_source = data_source
data_source.methods.grep(/^get_(*)_info$/){
Computer.define_component $1
}
end
def self.define_component(name)
define_method(name){
info = @data_source.send "get_#{name}_info", @id
price = @data_source.send "get_#{name}_price", @id
result= "#{name.to_s.capitalize}: #{info} ($#{price})"
return " * #{result}" if price >=100
result
}
end
end
重构Computer类(再一次)
用method_missing
class Computer
def initialize(computer_id,data_source)
@id = computer_id
@data_source = data_source
end
def method_missing(name,*args)
super if @ data_source.respond_to?("get_#{name}_info")
info = @data_source.send "get_#{name}_info", @id
price = @data_source.send "get_#{name}_price", @id
result= "#{name.to_s.capitalize}: #{info} ($#{price})"
return " * #{result}" if price >=100
result
end
end
my_computer = Computer.new(42,DS.new)
my_computer.cpu => * Cpu: 2.16 Ghz ($220)
覆写respond_to?()方法
class Computer
def initialize(computer_id,data_source)
@id = computer_id
@data_source = data_source
end
def method_missing(name,*args)
super if respond_to?(name)
info = @data_source.send "get_#{name}_info", @id
price = @data_source.send "get_#{name}_price", @id
result= "#{name.to_s.capitalize}: #{info} ($#{price})"
return " * #{result}" if price >=100
result
end
def respond_to?(method)
@data_source.respond_to?("get_#{method}_info")|| super
end
end
加入instance_methods方法,解决display的内部方法冲突
Object.instance_methods.grep /d/ #=>[:dup,:display,define_singleton_method]
class Computer
instance_mehods.each do |m|
undef_method m unless m.to_s =~ /^__|method_missing|respond_to?/
end
def initialize(computer_id,data_source)
@id = computer_id
@data_source = data_source
end
def method_missing(name,*args)
super if respond_to?(name)
info = @data_source.send "get_#{name}_info", @id
price = @data_source.send "get_#{name}_price", @id
result= "#{name.to_s.capitalize}: #{info} ($#{price})"
return " * #{result}" if price >=100
result
end
def respond_to?(method)
@data_source.respond_to?("get_#{method}_info")|| super
end
end
想起了以前写的业务结算的代码,回头补上代码。
此文章 短链接: http://dlj.bz/MR8c9t
Tag Cloud
AFNetworking(1)
AngularJS(2)
Devise(1)
Devops(1)
Homebrew(1)
MacOSX(11)
Rails4(2)
TTS(1)
Unauthorized(1)
analysis(1)
android(1)
apache(2)
api(1)
assets(5)
backup(3)
blog(1)
bower(1)
bundle(2)
cache(1)
capistrano(2)
capistrano3(2)
centos(4)
chrome-extension(1)
crontab(1)
css(1)
curl(1)
data(2)
deploy(2)
dlj(1)
dropbox(3)
elasticsearch(1)
fqa(1)
gem(7)
geobean(1)
gfw(1)
gis(1)
git(4)
github(2)
gitlib(1)
google(1)
httpd(1)
iOS(2)
java(1)
javascript(2)
jekyll(1)
js(2)
letsencrypt(1)
linode(2)
linux(16)
memcached(1)
mongodb(5)
mongoid(2)
mongomapper(1)
mtr(1)
mysql(2)
newrelic(1)
nginx(7)
nodejs(1)
notejs(1)
observer(1)
octopress(1)
omniauth-oauth(1)
openlayers(1)
paginate(2)
passenger(2)
pipeline(1)
plugin(2)
production(1)
proxy(3)
rails(23)
rails3(4)
rake(1)
restful_authentication(1)
ruby(28)
rvm(6)
search(1)
siege(1)
sinatra(2)
skill(7)
socks(1)
solr(1)
sql(2)
sqlserver(1)
ssh(6)
ssl(1)
story(4)
sublime-text(3)
sunspot(1)
sweeper(1)
theme(1)
tile(1)
tools(1)
ubuntu(19)
vagrantbox(2)
vps(2)
web(1)
webkit(1)
webpack(1)
win(3)
xcode(2)
yarn(1)
yum(1)
佛(3)
创业(1)
压力测试(2)
正则(1)
转载(7)