2011-10-10 65 views
1

即使現在,讓我們說我有一個自定義對象在Java觀察:如何當一個自定義對象改變它的擴展

public class TestObject { 

    private int value = 0; 

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

    public void increaseValue() { 
     value++; 
    } 

    } 

現在我想,當這個對象被修改就知道了。或者更具體地說,我想知道它的任何字段何時發生變化(在這種情況下,值)。此外,如果我擴展了TestObject,我仍然希望能夠監聽可能發生在該對象上的任何字段更改,包括如果該更改是針對新字段的新字段。

我已經做了一些研究,發現了各種各樣的隨java一起發佈的聽衆,但他們似乎都失敗了,他們要求您在方法結束時向聽衆發出呼叫。例如,increaseValue()也必須通知所有偵聽器TestObject的值已更改。顯然,這對我來說不起作用,因爲可擴展性是必須的,而且我不知道如果從該對象繼承的人將遵守他們必須通知偵聽器的要求。更不用說,編寫每個增變器方法的代碼似乎很痛苦,如果有任何光線可以在這個問題上得到解決,我們將不勝感激。

回答

1

您可以使用approach that Hibernate uses即儀器/代理您的類來爲您的POJO的getter和setter添加額外的(偵聽器)邏輯。但是你需要確保所有的代碼都只使用代理類。

+0

看到我的迴應 - 生產方面將解決必須使用代理的問題。 –

+0

儘管這看起來像一個可能很複雜的解決方案,但它與我所尋找的內容大致相符。 – Zargoon

1

更何況,它看起來像一個痛苦編程,對於每個 賦值函數方法

看看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 
+1

請參閱@Andrey Adamovich的回覆 - 代理將解決必須使用AspectJ ...的問題:-) –

1

顯然,這並不適合我,因爲可擴展性是必須的 有,我不知道,如果誰從該對象 繼承的人會堅持要求,他們必須通知聽衆

您的方法並不正確。

您不能強制派生類來保持基類的不變量,因爲繼承可以允許後代類以使其從父類的角度來看無效的方式來改變實現。

在你的情況下,派生類可能不會在修改時調用通知。

在這樣的情況下,你應該模擬以防萬一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);  

所以現在抓的是,物體的使用是通過持有人。
然後通知會發生。

+1

這是不正確的。繼承的理念是派生類需要服從基類的不變量。這是LSP的整個點,不是嗎?具體來說,基類方法的不變量是類型pf參數,返回值類型和異常。這裏的問題是基類想強制派生類的不變量。 –

+0

是的,你是對的。程序員負責執行不變量。我同意。這就是我在這裏所說的。無法強制執行基類的不變量。 – Cratylus

+0

不,程序員不負責執行不變量,該語言不會讓您打破不變量。該論點以「UnsupportedOperationException」分解,但理論上講,子類不能破壞超類不變式。 –

相關問題