首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

MOP——方法注入(3)

MOP——方法注入(3)

向单个实例中注入方法

前面介绍的是向整个类中注入方法,那么基于该类的所有对象都可以使用闭包中的方法。如果只是想扩展该类的某一个对象的方法,而不影响该类的其它对象,该如何处理呢?
其实不单是 Class,每个具体的对象也包含一个 metaClass,我们可将创建一个具体的 ExpandoMetaClass 实例,并将制定方法加入其中,然后将其赋给对应的具体对象,也可以将方法直接注入到具体的对象的 metaClass 上。

    //方式 1
    class Man{
        def talk(){}
    }
    def emc = new ExpandoMetaClass(Man)
    emc.sing = { -> ... }
    emc.initialize()
    def mike = new Man()
    mile.metaClass = emc
    mike.sing()
     
    //方式 2
    mike.metaClass.dance = { -> ...}
    mike.dance()
     
     
    //卸载之前注入的方法
    mike.metaClass = null

很明显方式 2 是最为优雅的,因此推荐使用方式 2。同时,当我们为一个对象注入了方法,在使用了一段时间不想使用后,那么很方便的卸载之前注入的方法。
ExpandoMetaClass 小结

使用 ExpandoMetaClass,无论是注入方法,还是调用方法,都比 Category 要优雅的多。因此推荐使用该方法。
但是要注意的是,如果对象想使用注入的方法,必须要先进行注入。如果在已经有对象产生之后再向类中注入方法,那么该对象无法调用注入的方法!!
因此使用 ExpandoMetaClass 进行注入,最好是在整个应用初始化时进行。

同时方法注入具有继承性。如果向 Object 注入了方法,那么所有的类都可以使用该方法。
使用 Minxin,trait 进行方法注入

这两种方式更像是开头提到的定义接口的实现方式。
个人感觉最为强大的方式是 Mixin 的方式。可以为类注入多个 Mixin,就好想让类实现了多个接口,同时接口中相同的方法,以后面加入的为准。
这里不再重点展开了。
Groovy Mixin 注入
Groovy 2.3 introduces traits
Mixins and traits
实现方式的优劣对比

    Category 存在的问题:其作用被限定在 use()块内,所以也就限定于当前执行的线程。进入该 use()块内的代码会在当前线程创建一个栈帧,并压入到当前线程的栈上,而当 use 代码块结束后,当前线程的栈会将刚刚压入的栈帧弹栈。但是如果频繁的调用 use 代码块,势必会对性能造成一定的影响。

    凡事都有两面性,Categoty 的使用 use 块,提供了更好的隔离性,我们可以再不同的地方,使用不同的分类,这也为类的扩展提供了灵活性。

    trait:缺点是在有类的修改权的情况下才能使用,类似接口。

    Mixin:其实是最强大的方式,但需要对其有进一步的了解,以防走火。。

这里推荐使用 ExpandoMetaClass。
返回列表