2014-03-25 83 views
3

也許我在這裏失去了一些東西,我承認我的OO技能不是我想要他們,但看看這example of the decorator pattern,我注意到UML聲明裝飾是兩者都是一個組件並且具有一個組件。這讓我爲難,在這一點它似乎是多餘的爲它是兩者,事實上,當我測試的「真實世界」的代碼,found here,並修改裝飾類看起來像這樣:裝飾模式與繼承和組合

abstract class Decorator /*: LibraryItem*/ { 
    protected LibraryItem libraryItem; 

    // Constructor 
    public Decorator(LibraryItem libraryItem) { 
     this.libraryItem = libraryItem; 
    } 

    public /* override */ void Display() { 
     libraryItem.Display(); 
    } 
} 

... 

class Borrowable : Decorator { 
    protected List<string> borrowers = new List<string>(); 

    // Constructor 
    public Borrowable(LibraryItem libraryItem) : base(libraryItem) { } 

    public void BorrowItem(string name) { 
     borrowers.Add(name); 
     libraryItem.NumCopies--; 
    } 

    public void ReturnItem(string name) { 
     borrowers.Remove(name); 
     libraryItem.NumCopies++; 
    } 

    public new /*override*/ void Display() { 
     base.Display(); 

     foreach (string borrower in borrowers) { 
      Console.WriteLine(" borrower: " + borrower); 
     } 
    } 
} 

我在這裏所做的只是通過註釋掉「:LibraryItem」來刪除is-a關係,但通過保留「protected LibraryItem libraryItem;」來保留has-a關係。我還注意到Display方法的替代方法用new關鍵字替換。盡我所能,這和原始代碼一樣。

我在這裏錯過了什麼嗎?裝飾器是否真的有必要從組件繼承? UML圖和實現代碼肯定會這樣,但我很好奇,如果有什麼我沒有看到或正確解決。

想法?

+1

不管我看你的代碼有多長時間,我都看不到這裏的裝飾器。裝飾器的基本思想是將相同的界面遞歸應用於裝飾對象。在這裏沒有任何這樣的事情。 –

+0

這是因爲我提供的代碼只是上述鏈接中提供的實際裝飾器的修改。 :) – EDanaII

回答

3

的裝飾圖案是假設

動態附加額外的責任的一個對象。 裝飾器提供了一種靈活的替代方法來繼承子類以擴展 功能。這種模式的設計使得多個裝飾器可以堆疊在每個其他的頂部,每次向覆蓋的方法添加新的功能。

實際上,你可以,如果你的裝飾類都是從同類型繼承,它是裝飾一個能鏈越來越多的裝飾從而增加了越來越多的責任,同時仍然能夠使用它在原來的基礎類被稱爲。

例如,您將無法將Borrowable傳遞到您需要LibraryItem的地方。你的例子只是一個組合的例子,而不是一個裝飾器的例子。

看看C#Stream及其裝飾器。

讓我們舉例說我有一個Document類。現在我可以有一個DocumentWithSpellCheckingDecorator和DocumentWithGrammarCheckingDecorator。我既可以使用裝飾器,也可以只使用其中一個,但是我仍然可以使用Document並可以用作Document,因爲我只是用更多的功能來裝飾它。也許這不是一個完美的例子,但希望它有幫助。

順便說一句,dofactor網站很容易理解,但有時並不完全消息。我也在網站上的其他模式中發現了這一點。

+0

好點。我非常關注已經存在的冗餘部分 - 我沒有想到繼承部分。當然,如果'this'關鍵字是隻讀的,這不會成爲問題。我想,如果我想,我可以手動將構造函數傳遞的對象中的每個屬性賦值給它的'this'計數器部分,但UML本身仍然將類定義爲is-a和has-a。 – EDanaII

2

裝飾部件IS-A部件,例如一個BorderedImage是裝飾有邊界的圖像,並且它可以在它的超類Image將用於任何地方被使用。

這意味着BorderedImage可以傳遞給任何使用Image的代碼,例如調用saveImage(Image image)的方法。

打破BorderedImageImage之間的繼承關係將阻止在代碼中使用裝飾圖像Image

這將意味着BorderedImage不再只是一個Image。因此,保持繼承關係對於保持Decorator模式的意義非常重要。