Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 自定义Guice范围,还是更好的方法?_Design Patterns_Scope_Guice - Fatal编程技术网

Design patterns 自定义Guice范围,还是更好的方法?

Design patterns 自定义Guice范围,还是更好的方法?,design-patterns,scope,guice,Design Patterns,Scope,Guice,我的问题是: 首先要知道我在写一个模拟。这是一个独立的应用程序,是单线程的。我基本上有两类对象,它们具有不同的范围要求 在整个模拟过程中应作为单例使用的类。随机的实例,例如 一起创建的类组,并且在组内,每个实例都应该被视为一个单例。例如,假设RootObject是顶级类,并且依赖于ClassA和ClassB,这两个类都依赖于ClassD。对于任何给定的RootObject,它的两个依赖项(ClassA和ClassB)都应该依赖于ClassD的同一个实例。但是,ClassD的实例不应在RootOb

我的问题是:

首先要知道我在写一个模拟。这是一个独立的应用程序,是单线程的。我基本上有两类对象,它们具有不同的范围要求

  • 在整个模拟过程中应作为单例使用的类。随机的实例,例如

  • 一起创建的类组,并且在组内,每个实例都应该被视为一个单例。例如,假设
    RootObject
    是顶级类,并且依赖于
    ClassA
    ClassB
    ,这两个类都依赖于
    ClassD
    。对于任何给定的
    RootObject
    ,它的两个依赖项(
    ClassA
    ClassB
    )都应该依赖于
    ClassD
    的同一个实例。但是,
    ClassD
    的实例不应在
    RootObject
    的不同实例之间共享

  • 希望这是有道理的。我可以想出两种方法。一种是将所有注入的对象标记为单例,创建根注入器,并在每次需要创建新的
    RootObject
    实例时派生一个子注入器。然后,
    RootObject
    的实例及其所有依赖项都作为单例创建,但是下次我去创建另一个
    RootObject
    时,范围信息就会被丢弃

    第二种方法是实现某种类型的自定义范围


    Guice文档给出了相互矛盾的建议。。。一方面,它说您应该有一个单一的注入器,理想情况下,只需调用一次就可以创建一些顶级类。另一方面,它说远离自定义作用域。

    我可以问一下为什么需要单例吗

    我不建议创建自定义范围。混合作用域的最佳且最简单的方法是注入提供程序而不是对象。通过提供程序,您可以从业务代码逻辑控制对象的范围


    有关详细信息,请参见此。

    您是否考虑过使用提供商?编写一个符合您的要求的文档是很容易的,例如:

    import com.google.inject.Provider
    
    class RootObjectProvider implements Provider<RootObject> {
    
        ...
    
        @Override
        RootObject get() {
            ClassD d = new ClassD( .... );
            ClassB b = new ClassB( ..., d, ...);
            ClassC c = new ClassC( ..., d, ...); // Note that b and c share d.
            return new RootObject(b, c, ...);
        }
    }
    
    import com.google.inject.Provider
    类RootObjectProvider实现提供程序{
    ...
    @凌驾
    RootObject get(){
    类别d=新的类别d(…);
    ClassB=新的ClassB(…,d,…);
    ClassC=新的ClassC(…,d,…);//注意,b和c共享d。
    返回新的RootObject(b,c,…);
    }
    }
    
    您可以通过两种方式使用提供程序:

  • 使用
    @提供的
    接口或
    .toProvider()
    绑定装饰将其绑定为提供程序
  • 直接注入提供程序并根据需要调用它来创建
    RootObject
    实例

  • 希望这能有所帮助。

    在我看来,您需要为
    RootObject
    的每个实例及其所有依赖项提供一个作用域

    在Guice中,您可以创建自定义范围,例如
    @ObjectScoped
    ,如下所示:

    @Target({TYPE,METHOD})
    @保留(运行时)
    @范围注释
    public@interface ObjectScoped{}
    
    现在只需将
    RootObject
    A
    B
    D
    放入此范围:

    @ObjectScoped
    公共类根对象{
    私人A;
    私人B,;
    @注入
    公共根对象(A、B){
    这个a=a;
    这个.b=b;
    }
    公共A getA(){
    返回a;
    }
    公共B getB(){
    返回b;
    }
    }
    @对象范围
    公共A类{
    私家侦探;
    @注入
    公共事务A(D){
    这个。d=d;
    }
    公共D getD(){
    返回d;
    }
    }
    //B和D也一样
    
    现在,每个
    RootObject
    都有自己的作用域。您可以将其实现为一个简单的
    HashMap

    公共类ObjectScope{
    私有映射,对象>();
    @抑制警告(“未选中”)
    公用T获取(密钥){
    return(T)store.get(key);
    }
    公共无效集(密钥,T实例){
    store.put(键、实例);
    }
    }
    
    要将这些作用域与Guice集成,您需要一个
    com.google.inject.Scope
    -实现,它允许您在
    模块中切换作用域和相应的连接

    公共类GuiceObjectScope实现作用域{
    //使其成为多线程的ThreadLocal。
    私有ObjectScope current=null;
    @凌驾
    公共提供程序作用域(最终密钥,最终提供程序未作用域){
    返回新的提供程序(){
    @凌驾
    公共部门得不到{
    //查找实例
    T instance=current.get(key);
    if(实例==null){
    //创建实例
    instance=unscoped.get();
    当前.set(键、实例);
    }
    返回实例;
    }
    };
    }
    public void enter(ObjectScope范围){
    电流=范围;
    }
    公众假期{
    电流=零;
    }
    }
    公共类ExampleModule扩展了AbstractModule{
    私有GuiceObjectScope objectScope=新的GuiceObjectScope();
    @凌驾
    受保护的void configure(){
    bindScope(objectScope.class,objectScope);
    //你的绑定
    }
    公共GUI对象范围getObjectScope(){
    返回对象范围;
    }
    }
    
    按如下方式初始化程序:

    ExampleModule=newexampleModule();
    喷油器喷油器=Guice.createInjector(模块);
    GuiceObjectScope objectScope=module.getObjectScope();
    
    创建
    RootObject
    的第一个实例及其相应范围:

    ObjectScope obj1=新的ObjectScope();
    输入(obj1);
    RootObject rootObject1=injector.getInstance(RootObject.class);
    leave();
    
    只需切换第二组对象的范围:

    ObjectScop