Python 、 PHP 、Ruby 这些语言为什么不抄下 Java 的动态代理来实现 AOP?

2018-03-15 10:30:40 +08:00
 zjsxwc

我看了 Java 的动态代理实现原理( http://blog.csdn.net/weidea/article/details/43348447 ) 的文章,

对应 Python、PHP、Ruby 这些语言来说山寨个 newProxyInstance 方法很简单啊,新手都可以花几小时就实现,为什么唯独就 Java 来说动态代理和 AOP 很火?

3554 次点击
所在节点    程序员
13 条回复
liprais
2018-03-15 10:52:17 +08:00
ruby 表示笑翻在地
zjsxwc
2018-03-15 10:53:35 +08:00
@liprais 猴子方法我知道。。
zjsxwc
2018-03-15 10:55:06 +08:00
@zjsxwc 但我觉得猴子方法反模式啊
fool079
2018-03-15 11:05:10 +08:00
python 表示????
vindurriel
2018-03-15 11:20:49 +08:00
静态语言才需要动态代理 动态语言不需要
这几种语言都可以实现 aop 具体方法 google 语言名称 + aop
至于为什么 aop 只有在 java 火 大概是因为 java 设计强制 oop 导致代码冗余 引入 aop 有助于缓解冗余吧
SlipStupig
2018-03-15 11:44:55 +08:00
python 表示很无辜....
janxin
2018-03-15 11:55:53 +08:00
动态语言都笑了-,-
tailf
2018-03-15 12:09:59 +08:00
动态语言的发明者就是不想写那一大坨代码才用动态的。。。。
toono
2018-03-15 12:22:37 +08:00
最近看 python 的书,感觉 python 就是让你突破在 其他语言很必要用设计模式才能方便实现和管理代码 的限制。

所以在其他语言应该用设计模式的地方,对 python 苛求模式的人,是不是在写 java 式 python ?因为很可能根据 python 的特性,不照搬设计模式可能会实现得更方便。


上面的小例证可以考虑 java 和 python 对于“策略模式”(来自《流畅的 python 》)
假设在不同的情况下需要执行不同的 run 方法

java 实现策略模式的时候,可能是几个子类继承同一个父类 A,并且都实现了 run 方法。这样在不同的类型情况下都能够调用子类实体的 run 方法,而且不同子类实体工作内容不相同。

python 的实现可以声明几个函数都放在一个数组中,然后选件选择运行哪个就好了。还可以用单分派泛函数 singledispatch 装饰器简单实现 java 的重载。

只能说每个语言都有它的特点
wwqgtxx
2018-03-15 12:23:00 +08:00
说反模式的只是因为你习惯了 java 的模式,但这并不是 ruby/python/php 的模式
sorra
2018-03-15 20:11:30 +08:00
@zjsxwc Java 的动态代理才是反模式,有很多限制。静态编织更好,但构建过程要复杂。
Ruby 的猴子补丁还可以,如果能冻结就是好模式了。
多学习。
Pool
2018-03-15 23:19:41 +08:00
设计模式这种东西本来就是针对静态的 OOP 才总结出来的套路。
对于动态语言来说有相应语法来支持,不是更好吗?
不用纠结设计模式这种模式这种东西,不增加代码的复杂度并实现了功能才是最好的
msg7086
2018-03-16 08:25:04 +08:00
很多设计模式是因为这些语言太不灵活,没法做到一些功能,而被迫创造出来的东西。
你贴的这篇文章我看了很久很久,算是看明白个大概了。
是说你拿到一个对象,想在外面包一层,然后动态改变其中的某个方法行为吧。
这不是 Ruby 的猴子补丁,猴子补丁是修改方法本身,你需要的是 Delegation,所以可以这样写:

require 'active_support'
require 'active_support/core_ext/module/delegation'

def wrap(source, overrides)
  klass = Class.new do
   delegate_missing_to :@source
   def initialize(source)
    @source = source
   end

   overrides.each do |func, code|
    define_method(func, &code)
   end
  end
  klass.new(source)
end

a = [1, 2]
a << 3
puts a
b = wrap(a, {:<< => ->(*args) { puts 'foo' } })
b << 4
b[1] = 5
puts b
puts a



# ruby test.rb
1
2
3
foo
1
5
3
1
5
3
不知道是不是你提到的东西。这里我 wrap 函数只是简单写下,但是应该是能够处理各种你想要的状况的,比如 before_hook after_hook wrap_hook 等等。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/438219

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX