开发者

How to observe when a custom object changes even after it's extended

开发者 https://www.devze.com 2023-04-11 17:16 出处:网络
So let\'s say I have a custom object in java: public class TestObject { private int value = 0; public TestObject(int value) {

So let's say I have a custom object in java:

   public class TestObject {

    private int value = 0;

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

    public void increaseValue() {
        value++;
    }

    }

Now I want to know when this object is modified. Or more specifically, I want to know when any of it's fields have changed (in this case value). Furthermore, if I extend TestObject, I still want to be able to listen to any field changes that might happen to that object, including if that change is to a new field new fields.

I've done some research and found of variety of listeners that come with java, but they all seem to fail in the area that they require you to开发者_Go百科 put calls to the listeners at the end of you're methods. For example, increaseValue() would also have to notify all of the listeners to the TestObject that value had changed. Obviously this doesn't work for me because extensibility is a must have and I do not know that if people who inherit from that object will adhere to the requirement that they must notify listeners. Not to mention, it seems like a pain to have to program that for each mutator method

If any light could be shed on this subject it would be greatly appreciated.


You can use approach that Hibernate uses i.e. instrument/proxy your classes to add additional (listener) logic around your POJOs' getters and setters. But then you need to ensure that all use only proxied classes.


Not to mention, it seems like a pain to have to program that for each mutator method

Take a look at The AspectJ Project. You could achieve this very easily with production aspect using a 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


Obviously this doesn't work for me because extensibility is a must have and I do not know that if people who inherit from that object will adhere to the requirement that they must notify listeners

Your approach is not in the correct path.

You can not enforce a derived class to keep the base's class invariants since inheritance can allow descendant classes to alter implementation in a way that makes them invalid from the viewpoint of the parent class.

In your case the derived class MAY or MAY not call the notification upon modification.

In cases like this you should model arround Composition and not Inheritence
Composition vs Inheritence

For your example:

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

Value knows how to increment itself.

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();  
       }  
    }

So all the code will be as follows:

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);    

So the catch now is that the usage of the objects are via the holder.
Then the notification will happen.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号