uioc icon indicating copy to clipboard operation
uioc copied to clipboard

依赖的继承和组合

Open otakustay opened this issue 10 years ago • 8 comments

在JAVA等语言中,有这样的方式:

public interface Actable {
    void setWeapon(Weapon weapon);

    Weapon getWeapon();
}

pubilc class Wizard implements Actable {
    // ...实现
}

public class Amazon impolments Actable {
    // ...实现
}

当需要所有的Actable都有固定的Weapon对象时,可以按照接口来进行配置:

<interface type="Actable">
    <property name="weapon" type="Sword" />
</interface>

这样无论是创建Wizard还是创建Amazon都会有Sword对象作为其weapon属性

这个功能可以节省大量的配置,对应我们的现状,如果一个Model对象有setGlobalData就意味着其需要GlobalData的实例,但每一个都这么配置有2个问题:

  1. 配置太多,到处要写一样的配置
  2. 如果一个Model从不依赖变成了依赖GlobalData,或者反过来,那么就要改配置

同时,在JAVA中,除了接口外,继承关系也一样会造成配置的继承


针对js,因为没有显式的接口这个概念,所以可能要分为类型的“定义”和类型的“组合”两种,其中“定义”依旧是普通的ioc配置,随后再通过一些判断来确认是否需要注入

ioc.configInterface(
    'requireGlobalData',
    function (instance) {  return instance.setGlobalData; },
    {
        properties: {
            globalData: { $ref: 'GlobalData' }
        }
    }
); 

对于继承,由于js并不容易判断继承链,JAVA也并不是子类一定会有父类的注入配置,所以使用一个importmix配置即可:

var config = {
    foo: {
        properties: {
            x: { $ref: 'x' }
        }
    },
    bar: {
        mix: 'foo',
        properties: {
            y: { value: 2 }
        }
    }
};

otakustay avatar Jun 23 '14 06:06 otakustay

大致看了一下,定义接口这个东西,简单的方法就是每个对象注入的时候去判断是否符合已经定义的接口,符合的话按接口的配置先注入,然后再跑对象自己的注入

但这对性能是有些影响的,因此是否可以引入一个“预编译”的过程,可能有以下几点:

  1. 接口定义判断“类型”而不是“实例”,即要typeof type.prototype.xxx === 'function'来判断,因为预编译时没有实例
  2. 对象的模块第一次被加载下来(未实例化)时,要预编译一次,即去匹配接口,有的话把配置混合到这个配置上(接口的优先级低)
  3. 获取对象逻辑就不变了

我比较不爽的是第1点要去判断类型而非实例,觉得访问类型的prototype其实不是个好的决定

otakustay avatar Jul 09 '14 09:07 otakustay

从 prototype 获取有些问题:

  1. 很难确保不会在实例上添加方法
  2. 很难保证说对象一定是 new 出来的,这样就不一定能够保证带有 prototype

我想是初始化的时候从实例获取接口依赖,然后缓存,接下来就不需要去解析接口依赖了,仅仅在第一次会有点性能消耗

Exodia avatar Jul 09 '14 09:07 Exodia

很难确保不会在实例上添加方法

我认为直接无视,或者给个接口重新config

很难保证说对象一定是 new 出来的,这样就不一定能够保证带有 prototype

嗯这是个问题

我想是初始化的时候从实例获取接口依赖,然后缓存,接下来就不需要去解析接口依赖了,仅仅在第一次会有点性能消耗

这个……如果不是单例,会有多次实例化,这个缓存后不是依旧会有你说的1的问题吗

otakustay avatar Jul 09 '14 09:07 otakustay

这个……如果不是单例,会有多次实例化,这个缓存后不是依旧会有你说的1的问题吗

多次实例化无所谓吧,我仅仅是需要从第一次的实例化中,获取这个实例符合的接口依赖,然后缓存到内部的配置中,下次实例化时,我直接从这个配置读取依赖给新实例注入

Exodia avatar Jul 09 '14 09:07 Exodia

是啊,所以第2次实例化前有给prototype加方法改变类型的定义,缓存还是会出问题,所以我觉得把1给无视掉

otakustay avatar Jul 09 '14 09:07 otakustay

我觉得接口配置可以简化的写:

interfaces: [
// interface1
     { method: 'setGlobalData', {  properties: {  globalData: { $ref: 'globalData' } }} }
]

Exodia avatar Jul 09 '14 09:07 Exodia

本质是个方法,简化写法用来生成这个方法好了,因为有些接口会是要求多个方法合在一起才算一个的啊

otakustay avatar Jul 09 '14 09:07 otakustay

是啊,所以第2次实例化前有给prototype加方法改变类型的定义,缓存还是会出问题,所以我觉得把1给无视掉

嗯,无视掉吧- -! 这样改 prototype 简直丧心病狂。

Exodia avatar Jul 09 '14 09:07 Exodia