標籤:des style blog http color java 使用 os
裝飾者模式,這個模式說我一直記憶深刻的模式,因為Java的IO,我以前總覺得Java的IO是一個類爆炸,自從明白了裝飾者模式,Java的IO體系讓我覺得非常的可愛,我們現在看看什麼是裝飾者,然後再來看如何去很爽的運用Java的IO(C#的IO則不同)
Component:這個是抽象介面(這裡的介面的意思不是interface關鍵字對應的介面,而是一個對應的口),以規範準備接收附加責任的對象。
Concrete Component:具體的組件,這個可以接收附加責任(裝飾)的類
Decorator:裝飾的抽象介面,實現一個與抽象構件介面一致的介面。
ConcreteDecorator:具體裝飾類,負責給具體組件加上裝飾的。
(每次想這個,我都覺得好抽象,不管那麼多,瞭解一下就好,先看例子再回來看)
我們直接來弄一個,軟飲(吃,這個東西最好做這個模式了)。
我們有[軟飲]是一個抽象存在的東西,所以肯定是我們的抽象組件
public abstract class BeverageComponent { public abstract string GetDescription(); public abstract double Cost(); }
有了抽象組建,我們來想想有那些具體的組建,咖啡(Espresso),House Blend(星巴克的首選咖啡,我喜歡,大家可以試試)
我們來建立這兩個類:
public class Espresso : BeverageComponent { public override string GetDescription() { return "Espresso"; } public override double Cost() { return 12; } } public class HouseBlend : BeverageComponent { public override string GetDescription() { return "HouseBlend"; } public override double Cost() { return 15; } }
我們為descrption欄位賦值上組建的名字,然後實現了抽象方法Cost,返回自己的價格。
到這裡我們擁有了抽象組建和具體組建,我們現在來構建一下抽象裝飾類
public abstract class BeverageDecorator : BeverageComponent {
//類裡面雖然什麼都沒有,但是我們可以在這裡添加一些專門屬於裝飾類的抽象方法. }
我們從UML圖上面看還是繼承了抽象組件,有了抽象的裝飾類,我們來構建一下具體的裝飾類
public class Milk : BeverageDecorator { private BeverageComponent _beverage; public Milk(BeverageComponent beverage) { _beverage = beverage; } public override string GetDescription() { return _beverage.GetDescription() + "+Milk"; } public override double Cost() { return _beverage.Cost() + 5; } } public class Sugar : BeverageDecorator { private BeverageComponent _beverage; public Sugar(BeverageComponent beverage) { _beverage = beverage; } public override string GetDescription() { return _beverage.GetDescription() + "+Sugar"; } public override double Cost() { return _beverage.Cost() + 2; } }
我們構建了Sugar和Milk兩個裝飾類,裡面帶有一個又參構造並要求傳入抽象組件的對象,這裡說裝飾者模式的核心,為什麼要求傳入一個抽象組件的對象呢?
這裡可以傳入具體組件的對象和裝飾類的對象,而且當你傳入了具體組件以後就不能夠繼續傳入其他的裝飾和組件了。關鍵的地方!!!
我們也就是可以認為,具體組件要做的是功能或者主要的東西,裝飾的東西對於具體組件是可有可無的,是用於做輔助的。我們來看看一杯加糖的牛奶的咖啡怎麼來。
class Program { static void Main(string[] args) { var beveage = new Milk(new Sugar(new Espresso())); Console.WriteLine("Descripiton:" + beveage.GetDescription()); Console.WriteLine("Cost:" + beveage.Cost()); Console.ReadLine(); } }
我們先建立一個牛奶對象,在傳入糖,最後把我們要的實物寫進去,來看下輸出。
輸出為:
到這裡,裝飾者模式就結束了。
我們來談談它的應用情境:
如果你有許多的功能,並且有許多的協助工具功能去輔助你這些具體功能,可以用裝飾者模式。
優點:
1. Decorator模式與繼承關係的目的都是要擴充項物件的功能,但是Decorator可以提供比繼承更多的靈活性。 2. 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合。 缺點: 1. 這種比繼承更加靈活機動的特性,也同時意味著更加多的複雜性。 2. 裝飾模式會導致設計中出現許多小類,如果過度使用,會使程式變得很複雜。 3. 裝飾模式是針對抽象組件(Component)類型編程。但是,如果你要針對具體組件編程時,就應該重新思考你的應用架構,以及裝飾者是否合適。當然 也可以改變Component介面,增加新的公開的行為,實現“半透明”的裝飾者模式。在實際項目中要做出最佳選擇。
Java的IO
這張圖說JAVA的API,我們的Component說InputStream. 除了我用紅筆圈出來的都說具體組建。我們走到FilterInputStream裡面看看
繼承了FilterInputStream的所有類都是裝飾類,所以FilterInputStream是抽象裝飾類。
也就是說繼承FilterInputStream這些類主要說為了輔助那些直接繼承了InputStream的具體組件類(Reader,Writer,OutputStream都說這樣的)
我們現在知道怎麼用了把
Stream stream=new BufferedInputStream(new FileInputStream()); 這樣我們主要功能說讀檔案,只不過在這個基礎上面加了一層緩衝。如果你要其他的輔助可以直接加進去,是不是很方便。