这个是 spring python 的例子,看上去还不错。
import springpython.aop as saop
class SampleService:
def method(self, data):
return "You sent me '%s'" % data
def m2(self, data):
return "You sent me 2'%s'" % data
class WrappingSvc(saop.MethodInterceptor):
def invoke(self, invocation):
return "Wrapped:" + invocation.proceed() + ":Wrapped"
service = saop.ProxyFactoryObject(target = SampleService(), interceptors = [WrappingSvc()])
print service.method("something")
print service.m2("something")
Wrapped:You sent me 'something':Wrapped Wrapped:You sent me 2'something':Wrapped
这个怎么看着不像 Python ...
Python 的风格难道不该是像下面这样
def m1():
return "m1"
def m2():
return "m2"
def wrapped(func):
@wraps(func)
def wrapper(*args, **kwargs):
return "<wrapped>{}</wrapped>".format(func(*args, **kwargs))
print m1()
print m2()
m1 = wrapped(m1)
m2 = wrapped(m2)
print m1()
print m2()
@fsword 第一,楼主提到的 springpyhton 不是每个人都熟悉,第二,今天双 11,被你厂的黑猫商城搞的大家都很忙,实在没空管这些一看看不明白的帖子。
这个算不算
class SampleService
def m1(data)
return "You sent me '#{data}'"
end
def m2(data)
return "You sent me 2'#{data}'"
end
end
class Wrapping
def initialize(target)
@target = target
end
def method_missing(m, *args)
return "Wrapped:#{@target.send(m, *args)}:Wrapped"
end
end
wrap = Wrapping.new(SampleService.new)
p wrap.m1("something")
p wrap.m2("something")
这不是 decorator 嘛?-__,-
https://github.com/fredwu/ruby_decorators
class Hi < RubyDecorator
def call(this, *args, &blk)
this.call(*args, &blk).sub('hello', 'hi')
end
end
class Batman < RubyDecorator
def call(this, *args, &blk)
this.call(*args, &blk).sub('world', 'batman')
end
end
class Catwoman < RubyDecorator
def initialize(*args)
@args = args.any? ? args : ['catwoman']
end
def call(this, *args, &blk)
this.call(*args, &blk).sub('world', @args.join(' '))
end
end
class World
extend RubyDecorators
def initialize
@greeting = 'hello world'
end
def hello_world
@greeting
end
+Batman
def hello_batman
@greeting
end
+Hi
+Catwoman
def hello_catwoman
@greeting
end
+Catwoman.new('super', 'catwoman')
def hello_super_catwoman
@greeting
end
end
world = World.new
world.hello_world # => "hello world"
world.hello_batman # => "hello batman"
world.hello_catwoman # => "hi catwoman"
world.hello_super_catwoman # => "hello super catwoman"
aspect 是一种新的编程范型,已经有多年历史了,大型程序比较有用。主要用途是横切,比如常见的 log,安全,缓存,事务等可以写到 aspect 里面。spring 框架就是靠这个成名。
rubu 要写多个串接的估计也不容易。
class SampleService
def m1(data)
return "You sent me '#{data}'"
end
def m2(data)
return "You sent me 2'#{data}'"
end
end
class Wrapping
def initialize(target, wrappers = [])
@target = target
@wrappers = wrappers
end
def method_missing(m, *args)
return "#{@wrappers.map(&:perform_befor).join(':')}:#{@target.send(m, *args)}:#{@wrappers.map(&:perform_after).join(':')}"
end
end
class WrapperDemo1
def perform_befor
"demo1 befor"
end
def perform_after
"demo1 after"
end
end
class WrapperDemo2
def perform_befor
"demo2 befor"
end
def perform_after
"demo2 after"
end
end
wrap = Wrapping.new(SampleService.new, [WrapperDemo1.new, WrapperDemo2.new])
p wrap.m1("something")
p wrap.m2("something")
#16 楼 @chenge 1.9.x 下 BasicObject 可做 blank class 用。1.8.x 需要自己处理一下,或使用 gem "blankslate"。
Ruby 的文档已经说的详细了:) http://ruby-doc.org/core-1.9.3/BasicObject.html
#19 楼 @chenge 是重要的。blank class 的作用主要是防止名字空间被污染。 以此例来说,Wrapping 默认是从 Object 继承,这样会导致 Wrapping.new 创建的对象拥有来自 Object 及 Kernel 的方法。作为一个代理对象,这有可能会与被代理的对象有方法的冲突。 所以,在实现类似的代理类时,通常的做法是让它继承一个 blank class。
比如还是以此例稍微修改一下,然后你看看结果
class SampleService
def m1(data)
return "You sent me '#{data}'"
end
def m2(data)
return "You sent me 2'#{data}'"
end
def method(data)
return "You sent me 3'#{data}'"
end
end
...省略......
p wrap.m1("something")
p wrap.m2("something")
p wrap.method("something")
看不懂啊,这不就是一个简单 的 mixin 功能吗?
哦 其实是个 decorator
class SampleService
def meth(data)
"You sent me #{data}"
end
def m2(data)
"You sent me 2#{data}"
end
end
class Wrapper
def invoke(&blk)
"Wrapped: " + blk.call + " :Wrapped" if block_given?
end
end
module Decorator
def initialize(service, wrap)
@service = service
@wrap = wrap
end
def method_missing(meth, *args)
if @service.respond_to?(meth)
@wrap.invoke { @service.send(meth, *args) }
else
super
end
end
def respond_to?(meth)
@service.respond_to?(meth)
end
end
class Service
include Decorator
end
service = Service.new(SampleService.new, Wrapper.new)
puts service.meth("something")
puts service.m2("something")
class World
extend RubyDecorators
def initialize
@greeting = 'hello world'
end
def hello_world
@greeting
end
+Batman
def hello_batman
@greeting
end
+Hi
+Catwoman
def hello_catwoman
@greeting
end
+Catwoman.new('super', 'catwoman')
def hello_super_catwoman
@greeting
end
end
这里的+Hi, + 号是什么意思?
class RubyDecorator
def self.+@
RubyDecorators::Stack.all << self
end
def +@
RubyDecorators::Stack.all << self
end
end