2011-11-03 84 views
0

假設我們有下面的類結構:聽繼承類的特定事件

public class Fruit 
{ 
    public event EventHandler<RipeEventArgs> Ripe; 
} 

public class Apple:Fruit 
{ 
    public event EventHandler<FallEventArgs> FallFromTree; 
} 

public class Farm 
{ 
    List<Fruit> fruits; 
} 

public class Farmer 
{ 
    private Farm myFarm; 

    public Farmer() 
    { 
     // listen to all FallFromTree events coming from the farm 
     myFarm.WHAT += AppleFallen; 
    } 

    public void AppleFallen(object sender, FallEventArgs e) {} 
} 

問題:如何確保農民能夠從在農場的任何蘋果聽取所有FallFromTree事件和任何將來會創建的蘋果?

我在考慮冒泡事件,但這意味着Farm應該定義每個事件也包括在Apple。問題是,我將通過不同的活動創造出許多不同的成果,重要的是一些特殊的農民只能聆聽來自農場的特定事件。因此,定義Farm中的每一種新事件似乎都不是我的解決方案。

+0

這是一個家庭作業嗎? –

+0

不,我正在試圖找到一種方法,不要創建一個巨大的農場類。 – Marnix

+0

爲什麼不添加一個枚舉來描述一個農民可能感興趣的東西。這與農民不需要了解具體的水果事件有什麼不同。但有了相當大的優勢,你現在只需要一個事件。 –

回答

1

只是讓Farm瞭解Farmer而非Farmer瞭解Farm

public class Fruit 
{ 
    public event EventHandler<RipeEventArgs> Ripe; 
} 

public class Apple:Fruit 
{ 
    public event EventHandler<FallEventArgs> FallFromTree; 
} 

public class Farm 
{ 
    List<Fruit> fruits; 
    Farmer farmer; 

    public Farm(Farmer farmer) 
    { 
     this.farmer = farmer; 
    } 

    public void AddFruit(Fruit fruit) 
    { 
     farmer.RegisterForEvents(fruit); 
     fruits.Add(fruit); 
    } 
} 

public class Farmer 
{ 
    private Farm myFarm; 

    public Farmer() 
    { 

    } 

    public virtual void RegisterForEvents(Fruit fruit) 
    { 
     //Farmer decides what events it is interested in: can override in derived classes 
     if(fruit is Apple) 
     { 
      ((Apple)fruit).FallFromTree += AppleFallen; 
     } 
    } 

    public void AppleFallen(object sender, FallEventArgs e) {} 
} 

fruit is Apple條款是不理想,但我認爲你唯一可以做的事情有兩種實現雙重分發或對Farmer每種類型的Fruit不同的方法。

+0

這聽起來很有希望。我將討論我的團隊中的可能性。 – Marnix

+0

這可能是完美的答案,但不幸的是,我們有更多的需求,這種模式無法促成。例如。人們也應該能夠訂閱所有事件,而不知道這些事件是什麼。但對於我問的問題,這將是一個正確的實施。謝謝。 – Marnix

+0

好的,謝謝你的接受。根據您的一般要求:最終需要做出關於「Farmer」應該訂閱哪些事件的決定,因此儘管您可以隱藏來自「Farmer」本身的行爲需要居住在某處的知識。如果這個責任似乎不適合你的任何現有對象,那麼也許這表明你需要引入一個新的類來履行這個角色。祝你好運。 –

0

您需要實現一個處理命令的命令處理程序。讓蘋果落下是一個命令的例子。

public class MakeAppleFallCommandHandler 
{ 
    public void Execute(Apple apple) 
    { 
     //This method would be called whenever any apple in the farm falls 

     FallFromTree(apple); 
    } 

    public event EventHandler<FallEventArgs> FallFromTree; 
} 

然後在農民階層,你可以訂閱MakeAppleFallCommandHandler.FallFromTree。這受到CQRS的啓發。

+0

你會離開所有這些命令處理程序嗎?它看起來像一個很好的模式,但我不明白這不會顯着增加'Farm'代碼,因爲每個新事件需要Farm中的一個新的CommandHandler來訂閱。 – Marnix

+0

你的邏輯是這樣的,你會在你的應用程序中有很多代碼。這只是一個類有很多代碼的問題,因爲許多類都有一些代碼。在上面的模式中,您可以編寫一個訂閱管理器類,其中包含哪個服務器場訂閱哪個命令處理程序的邏輯。 – Suhas

0

那麼,如果農場有水果,那麼它只能訂閱水果事件。

在您的基類中定義一個虛擬事件,即Fruit,然後在您的不同Fruits子類中覆蓋它,就像蘋果一樣,它會是FallFromTree。

看到這個更多詳情 C#: What are virtual events and how can they be used?

+0

這會極大地增加水果類,也意味着任何一種水果都會知道如何從樹上掉下來,而一些水果甚至不會從樹上長出來。所以,這只是一個巨大農場的解決方法。 – Marnix

+0

不,我的意思是Fruit類會有一個稱爲ChildEvent的通用事件。每個孩子都會以自己的方式暴露它。就像蘋果將暴露FallFromTree for ChildEvent一樣。其他水果將根據其屬性覆蓋他們自己的兒童活動。就像在根中生長的水果一樣,會暴露出GrownFromRoot – Anand

+0

但是這意味着每個水果只能有一個事件。這當然不是這種情況。我希望他們也有多個活動。 – Marnix