【问题标题】:How to observe when a custom object changes even after it's extended如何观察自定义对象何时更改,即使它已扩展
【发布时间】:2011-10-10 07:13:24
【问题描述】:

假设我在 java 中有一个自定义对象:

   public class TestObject {

    private int value = 0;

        public TestObject(int value) {
                this.value = value;
        }

    public void increaseValue() {
        value++;
    }

    }

现在我想知道这个对象何时被修改。或者更具体地说,我想知道它的任何字段何时更改(在本例中为值)。此外,如果我扩展 TestObject,我仍然希望能够侦听该对象可能发生的任何字段更改,包括该更改是否针对新字段新字段。

我进行了一些研究,发现 java 附带的各种侦听器,但它们似乎都失败了,因为它们要求您在方法结束时调用侦听器。例如, increaseValue() 还必须通知 TestObject 的所有侦听器值已更改。显然这对我不起作用,因为可扩展性是必须具备的,而且我不知道从该对象继承的人是否会遵守他们必须通知听众的要求。更不用说,必须为每个 mutator 方法编程似乎很痛苦

如果能对这个问题有所了解,将不胜感激。

【问题讨论】:

    标签: java inheritance field onchange listeners


    【解决方案1】:

    您可以使用approach that Hibernate uses 即仪器/代理您的类来围绕您的 POJO 的 getter 和 setter 添加额外的(侦听器)逻辑。但是你需要确保所有这些都只使用代理类。

    【讨论】:

    • 查看我的回复——生产方面可以解决必须使用代理的问题。
    • 虽然这看起来可能是一个复杂的解决方案,但它最符合我的要求。
    【解决方案2】:

    更不用说,必须为每个人编写程序似乎很痛苦 修改器方法

    看看The AspectJ Project。您可以使用pointcut for field assignment 在生产方面轻松实现这一目标。

    public privileged aspect TestObjectObserver {
        before(Object o) : set(* TestObject.*) && args(o) {
          // notify listeners
        }
    } 
    
    // runs before field assignment to any field of TestObject. The value to be
    // assigned is converted to an object type (int to Integer, for
    // example) and named o in the body
    
    // the aspect needs to be declared privileged so access private fields
    

    【讨论】:

    • 查看@Andrey Adamovich 的回复 - 代理可以解决必须使用 AspectJ 的问题 ... :-)
    【解决方案3】:

    显然这对我不起作用,因为可扩展性是必须的 有,我不知道如果从那个对象继承的人 将遵守他们必须通知听众的要求

    您的方法不正确。

    您不能强制派生类保持基类的不变量,因为继承可以允许后代类以某种方式改变实现,从而使它们从父类的角度来看是无效的。

    在您的情况下,派生类可能或可能不会在修改时调用通知。

    在这种情况下,您应该建模 arround Composition 而不是 Inheritence
    Composition vs Inheritence

    你的例子:

    class Value{    
        private int value;   
         public void increaseValue() {  
                value++;  
         }  
    }
    

    值知道如何增加自己。

    class ValueHolder extends Observable {  
           private Value theValue;  
           public ValueHolder(Value v){  
              theValue = v;  
           }
           public void modifyValue(String methodName)(){  
               Method method = theValue.getClass().getMethod(methodName, null);  
               method.invoke(theValue,null);//Since it has no args           
               setChanged();  
               notifyObservers();  
           }  
        }
    

    所以所有代码如下:

    ValueHolder vh = new ValueHolder(new Value(10));  
    //registration of listeners
    vh.modifyValue("increaseValue");  
    
    //So if you extend the Value 
    class DerivedValue extends Value{    
        private int y;   
         public void increaseY() {  
                y++;  
         }  
    }  
    
    ValueHolder vh = new ValueHolder(new DerivedValue());  
    //registration of listeners
    vh.modifyValue("increaseY);    
    

    所以现在的问题是对象的使用是通过持有人进行的。
    然后通知就会发生。

    【讨论】:

    • 这是不正确的。继承背后的想法是派生类需要遵守基类的不变量。这就是 LSP 的全部意义,不是吗?具体来说,基类方法的不变量是类型 pf 参数、返回值类型和异常。这里的问题是基类想要在派生类上强制不变量。
    • 是的,你是对的。执行不变量是程序员的责任。我同意。这也是我在这里要说的。无法强制执行基类的不变量。
    • 不,强制不变量不是程序员的责任,语言不允许你破坏不变量。这个论点与UnsupportedOperationException 不同,但理论上这个想法是子类将无法破坏超类不变量。
    • @Hemal:我不确定我们在谈论同一件事。例如,如果在基类中,条件 a < b 在所有情况下都应该保持有效(ab 是成员字段)如何确保扩展类和覆盖方法的程序员保留此不变量?你不能。这是我的意思
    • 对不起,我有点困惑。你们能否为我提供更多关于我应该研究的方向?
    猜你喜欢
    • 2019-04-08
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多