2011-04-21 71 views
5

我要裝飾(裝飾設計模式)一個普通的基類,但我需要的方法裝飾是受保護的。請參閱示例:Java裝飾模式:我可以裝飾受保護的方法嗎?

public class AbstractActor { 
    public void act(){...}  //Delegates its actions to doAct() based on some internal logic 
    protected void doAct(){...} 
} 

子類旨在覆蓋doAct(),我需要在其中注入一些功能。我可以重寫doAct,但是我的裝飾器類無法訪問正在裝飾的實例的受保護方法doAct()。例如:

public class ActorDecorator extends AbstractActor { 
    AbstractActor decoratedInstance; 
    public ActorDecorator(AbstractActor decoratedInstance){ 
     this.decoratedInstance = decoratedInstance; 
    } 
    protected void doAct(){ 
     //Inject my code 
     decoratedInstance.doAct(); //Can't call protected method of decoratedInstance 
    } 
    //Other decorator methods 
} 

有沒有解決這個問題的方法?

回答

6

如果您將AbstractActorActorDecorator放在同一個包中,您將能夠訪問受保護的方法。

0

你如何擴展你正在嘗試裝飾的類,並提供一個調用受保護函數(你將有權訪問)的公共函數,然後修飾擴展類? 所以在你的榜樣:

public class ToDecorateActor extends AbstractActor { 
public void publicAct() { 
    doAct(); 
} 
} 

public class ActorDecorator { 
    ToDecorateActor decoratedInstance; 
    public ActorDecorator(ToDecorateActor decoratedInstance){ 
     this.decoratedInstance = decoratedInstance; 
    } 
    protected void doAct(){ 
     //Inject my code 
     decoratedInstance.publicAct(); 
    } 
    //Other decorator methods 
} 
+0

這裏的問題是,我需要裝飾的AbstractActor(和它的衆多的子類)的實例,而不是ToDecorateActor的實例。例如,如果我給出了,hollywoodActor(HollywoodActor擴展了AbstractActor),我無法調用新的ActorDecorator(hollywoodActor)。 – 2011-04-21 10:46:47

+0

我不喜歡這個答案。基本上你正在將受保護的方法改爲公共方法。 – 2011-04-21 10:50:23

+0

當一個類設計師保持一種方法的保護,那麼它應該保持這種方式!如果你以這種方式違反封裝,那麼就是爲每個人設置了非常糟糕的編程示例,並且給類的消費者帶來了更多麻煩。 – Nilesh 2011-04-21 11:50:23

-1

當一個類設計則保留保護的方法,它應該保持這種方式!如果你以這種方式違反封裝,那麼就是爲每個人設置了非常糟糕的編程示例,並且給類的消費者帶來了更多麻煩。

話雖如此,在你的情況下,什麼阻止你注入你的代碼在調用覆蓋act()?無論如何,請撥打您的受保護方法doAct()

希望有所幫助。

+0

act()有相當多的邏輯,它可能會或可能不會調用doAct )取決於條件。我只想在調用doAct()時注入功能。在這種情況下,我需要複製act()的邏輯,這將嚴重違反良好的編程原則。它受保護的事實是,子類可以覆蓋它。在這種情況下,我是一個子類,使用Decorator模式來避免子類化大量的AbstractActor子類。這個庫的創建者創建了doAct(),但我並沒有將它用於裝飾。 – 2011-04-22 04:13:22

+0

「當一個類設計師保持一種方法的保護時,它應該保持這種方式!」這不是真的。當你在Jar文件中使用類時,比如當你使用框架時,改變行爲的唯一方法是通過擴展,但是有些情況下你需要運行時擴展,這需要組合,爲此你需要公共方法或定位你的課程在同一個包裏。 – CCC 2012-05-06 19:53:01

0

我覺得使用相同的包名稱是最好的答案,但我還有一個彈出到我自己的想法,我會評論。

應該可以使用Aspect Oriented Programming(例如AOP,AspectJ)來爲doAct()方法注入建議。由於我在Spring環境中工作,並且可以使用AOP編程,因此我可能會考慮使用此功能。

我已經添加了這個答案作爲一點思考的食物,我還沒有使用AOP來處理這個問題。