2010-01-18 70 views
3

我理解裝飾模式,用最簡單的術語。這個想法是一個類包裝另一個類,其中裝飾器方法希望在裝飾對象上調用相同方法之前和/或之後運行其他代碼。精細的裝飾模式

但是,我遇到了不能簡單地調用裝飾方法的情況,因爲它有一些不希望的副作用。不過,我想希望大部分裝飾方法運行。

所以我相信我需要將裝飾的方法拆分爲多個方法,然後在裝飾器中我可以調用其中的一些,運行我的裝飾代碼,然後調用其他一些 - 錯過了副作用,我不想。

但是,爲了保持多態性,這意味着將這些方法添加到裝飾對象和裝飾對象實現的接口。這是不可取的;他們不應該公開,並且它實際上意味着裝飾的班級知道如何裝飾。

我認爲,模板模式可能是比較合適的,其中一個抽象基類調用每個依次更小的方法,這裏的「裝飾」只是提供一個替代實現它關心的人。然而,這不完全是「繼承的構成」,所以你推薦什麼?

回答

1

這聽起來像您的API違反Command-Query Separation所以你最好的辦法是重新設計的API。

但是,如果我錯了或重新設計是不可能的,也許你可以在裝飾類的方法分成兩種方法不改變接口。

public interface IMyInterface 
{ 
    Foo GetFoo(Bar bar); 
} 

public class MyClass : IMyInterface 
{ 
    public Foo GetFoo(Bar bar) 
    { 
     this.DoSomethingWithSideEffects(bar); 
     return this.DoSomethingToGetFoo(bar); 
    } 

    public Foo DoSomethingToGetFoo(Bar bar) 
    { 
     // ... 
    } 

    public void DoSomethingWithSideEffects(Bar bar) 
    { 
     // ... 
    } 
} 

public class MyDecorator : IMyInterface 
{ 
    private readonly MyClass mc; 

    public MyDecorator(MyClass mc) 
    { 
     // put Null Guard here... 
     this.mc = mc; 
    } 

    public Foo GetFoo(Bar bar) 
    { 
     return this.mc.DoSomethingToGetFoo(bar); 
    } 
} 

請注意,MyDecorator裝飾MyClass而不是IMyInterface。

+1

除了名字我不熟悉CQS - 我以什麼方式違反了它? – 2010-01-19 00:14:26

+0

我並不是說你違反了CQS,但不想要的副作用往往是朝着這個方向發展的標誌。對於CQS,方法要麼沒有副作用,要麼只有*副作用。然而,在後一種情況下,副作用絕不是不希望的。 – 2010-01-19 08:27:28

2

像Template這樣的聲音最適合您的場景。我不會在不需要時強制組合...... this conversation說得最好,「...這條規則的例外:當你應該使用繼承,即如果你需要模擬替代性。」

+0

同意給定的場景聽起來非常像模板模式。 – 2010-01-18 17:29:43