一种实现模式:钩子方法 (An implement pattern: hook method)
访问量: 3355
我们经常会用到hook 方法(钩子方法). 例如: before, after, ... 比如rails,比如delayed_job中。 ( We have been seen this kind of code everywhere: before, after... in rails or other libraries such as delayed_job. they are called 'hook method' )
最基本的设想是这样的 ( the simplest implementation is as below )
def run before core_method after end def core_method; puts 'running the core method' ; end def before; puts 'something happens before hand' ; end def after; puts 'finally...' ; end run # => 'something happens before hand' # => 'running the core method' # => 'finally...'
尽管上面的代码也工作, 但是还有更好的办法。可读性更强。比如delayed_job 中所使用的: ( Yes, the above code works, however there's a better way to improve the readability. see the implementation from delayed_job as below )
class ParanoidNewsletterJob < NewsletterJob def perform emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) } end def before(job) record_stat 'newsletter_job/start' end
我们可以看到,delayed job 源代码中,中把hook进一步写成了一个macro ( 模拟宏) ( We could find that Delayed_job 's source code implements the hooks as a class macro )
def hook(name, *args) if payload_object.respond_to?(name) method = payload_object.method(name) method.arity == 0 ? method.call : method.call(self, *args) end rescue DeserializationError # do nothing end
然后就可以写成更加自然/理所当然/一目了然的方式: ( Then, the code is more straight forward...)
def invoke_job hook :before # instead of: payload_object.send(:before) payload_object.perform hook :success rescue Exception => e hook :error, e raise e ensure hook :after end
怎么样? 使用了 "hook" 做为macro, 是不是一目了然,核心方法 payload_object.perform 赫然出现。hooks 把它围绕在中心。效果是不是比原来的代码要容易了不少呢? ( see it? it's more obvious that 'before', 'success' are hooks and the 'payload_object.perform' is the core method. )