V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zjsxwc
V2EX  ›  程序员

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

  •  
  •   zjsxwc ·
    zjsxwc · 2018-03-15 10:30:40 +08:00 · 3569 次点击
    这是一个创建于 2448 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    第 1 条附言  ·  2018-03-15 11:04:08 +08:00
    ruby、python 有猴子补丁,
    php 有__call 方法

    感觉都有点反模式
    第 2 条附言  ·  2018-03-15 21:29:16 +08:00
    思考了下。

    对于动态语言,函数、方法 本身就是对象,他们天生就可以被赋值与传递,于是用猴子补丁这种手段,可以动态修改实例对象已经拥有的方法,也就是说其实我们可以随意拿捏对象,而不用管他最初的 class 是什么,这对于 ruby\python\php\js 来说很简单( php 需要稍微修改下__call 方法来实现 https://phpfashion.com/monkey-patching-v-php )。

    而 Java 是做不到这种任性地修改对象的方式,只能通过动态代理的方式来实现。
    13 条回复    2018-03-16 08:25:04 +08:00
    liprais
        1
    liprais  
       2018-03-15 10:52:17 +08:00   ❤️ 3
    ruby 表示笑翻在地
    zjsxwc
        2
    zjsxwc  
    OP
       2018-03-15 10:53:35 +08:00
    @liprais 猴子方法我知道。。
    zjsxwc
        3
    zjsxwc  
    OP
       2018-03-15 10:55:06 +08:00
    @zjsxwc 但我觉得猴子方法反模式啊
    fool079
        4
    fool079  
       2018-03-15 11:05:10 +08:00
    python 表示????
    vindurriel
        5
    vindurriel  
       2018-03-15 11:20:49 +08:00 via iPhone
    静态语言才需要动态代理 动态语言不需要
    这几种语言都可以实现 aop 具体方法 google 语言名称 + aop
    至于为什么 aop 只有在 java 火 大概是因为 java 设计强制 oop 导致代码冗余 引入 aop 有助于缓解冗余吧
    SlipStupig
        6
    SlipStupig  
       2018-03-15 11:44:55 +08:00
    python 表示很无辜....
    janxin
        7
    janxin  
       2018-03-15 11:55:53 +08:00
    动态语言都笑了-,-
    tailf
        8
    tailf  
       2018-03-15 12:09:59 +08:00
    动态语言的发明者就是不想写那一大坨代码才用动态的。。。。
    toono
        9
    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
        10
    wwqgtxx  
       2018-03-15 12:23:00 +08:00 via iPhone
    说反模式的只是因为你习惯了 java 的模式,但这并不是 ruby/python/php 的模式
    sorra
        11
    sorra  
       2018-03-15 20:11:30 +08:00
    @zjsxwc Java 的动态代理才是反模式,有很多限制。静态编织更好,但构建过程要复杂。
    Ruby 的猴子补丁还可以,如果能冻结就是好模式了。
    多学习。
    Pool
        12
    Pool  
       2018-03-15 23:19:41 +08:00
    设计模式这种东西本来就是针对静态的 OOP 才总结出来的套路。
    对于动态语言来说有相应语法来支持,不是更好吗?
    不用纠结设计模式这种模式这种东西,不增加代码的复杂度并实现了功能才是最好的
    msg7086
        13
    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 等等。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2318 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:11 · PVG 00:11 · LAX 08:11 · JFK 11:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.