做者 點先生 日期 2018.8.26java
最近一直不在狀態,月初就被博客質量的事給弄的情緒低落,以後羣裏又走了兩個朋友,心情是一直在低谷徘徊,博客也是不想寫,狀態一天不如一天,總之就是一句話,不想工做。因此…… 有沒有小(fu)姐(luo)姐(li)私聊我啊!設計模式
設計模式剛入門的小夥伴能夠先看看這篇《設計模式入門》,在文章末尾也將列出「設計模式系列」文章。歡迎你們關注留言投幣丟香蕉。天星技術團QQ:557247785。bash
爲了方便理解,咱們先舉一些例子。
人是一個類,要上街的話,人就得穿衣服,褲子,鞋子,這是最簡單的裝扮,有些人還會打領帶、揹包、戴帽子等等。在這個例子中,「人」是一個被裝飾者,衣服褲子鞋子是裝飾者。在整個打扮過程當中,被裝飾者類是不會被更改的,產生變化的是裝飾者類的數量。
在吃火鍋以前,咱們會調料碗。那麼空碗就是被裝飾者,油、香菜、蔥花就是裝飾者;
點菜這一步驟,也是裝飾者模式,鴛鴦鍋就是被裝飾者,麻辣牛肉、毛肚、鴨腸、菌肝、千層肚、鴨血、紅糖餈粑就是裝飾者;
裝飾模式就是在不改變原類文件和使用繼承的狀況下,動態地擴展一個對象的功能。
聊到這裏,有沒有一點餓? app
首先看一下裝飾者模式的UML圖 ide
我是按括號裏的文字來記憶的,會比較容易記住。剛剛咱們舉例寫到的「人」就是抽象組件;「男人\女人」就是具體組件;「裝飾品」就是抽象組件;「帽子」就是具體組件;函數
咱們先來分析一下上面提到的人化妝的例子。首先來建立四個參與者。 1.抽象組件Human ,給他一個自我介紹的描述,再添加一個方法,說出本身穿了什麼。post
abstract class Human {
open var description = "I'm a human."
abstract fun getDress() : String
}
複製代碼
class Male : Human() {
override var description: String
get() = "我是男性"
set(value) {}
override fun getDress(): String {
return "我穿了內褲"
}
}
複製代碼
abstract class Decoration : Human() {
abstract override var description: String
}
複製代碼
class Hats : Decoration() {
override var description: String
get() = " 我有帽子"
set(value) {}
override fun getDress(): String {
return "帽子"
}
}
複製代碼
如今有了四個參與者,結構也按照UML寫好了。那接下來就是包裝了。 穿衣服時,咱們會一件一件的穿(沒有誰會同時穿吧?),因此,咱們穿了褲子後,再穿衣服時,被裝飾者是「男\女人+褲子」。看圖! 學習
裝飾者是一個一個去包裹被裝飾者,這裏要注意,衣服和褲子跟男人是同一個超類,咱們在包裹的時候,須要把被包裝的對象(被包裝的對象多是具體組件,也多是已經被裝飾者裝飾以後的具體組件),傳到裝飾者中,因此咱們須要在具體裝飾者類中添加一個超類參數。這樣才能獲得被包裝對象的全部參數。因此剛剛的具體裝飾者類還沒寫完,補充完整應該是:ui
class Hats(var human: Human) : Decoration() {
override var description: String
get() = "帽子"
set(value) {}
override fun getDress(): String {
return human.getDress() + " 帽子"
}
}
複製代碼
再創造幾個具體裝飾者類,此時項目結構就是這樣的。 this
class MainActivity : AppCompatActivity() {
var superMan : Human? = Female()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
superMan = Cloak(Hats(this.superMan!!))
tv_textview.text = superMan?.description + superMan?.getDress()
}
}
複製代碼
結果以下:
經過例子應該對裝飾模式有個初步的理解了。再寫demo的時候也只須要記住一下幾步:
裝飾模式優勢: 裝飾模式比普通的繼承更加靈活,可以在運行時更改組件的功能。而繼承的類在運行前就決定了全部功能。
缺點: 會創造不少的小類。別人看代碼的時候會很腦袋痛。
注意: 裝飾模式中,裝飾的順序很重要。先穿「褲子」再穿「衣服」跟先穿「衣服」後穿「褲子」是不同的
我當初決定要學習設計模式的初衷,是爲了看源碼。如今咱們就來一塊兒來看看源碼, 我也會順便把我在這當中學到的一些看源碼的方式方法說出來。大佬們請忽略這句話。
查看源碼技巧一:查看它的父類子類並畫圖。
在AS右上角有個hierarchy按鈕,點它能夠查看當前類的直接父類和所有子類。
java I/O 是比較龐大的一個庫,若是直接看其代碼,很難知道每一個類都在幹啥,也不知道它究竟怎麼運做的。實話說,我之前就看暈了。 經過看它的類結構。咱們能畫出這樣一張圖:
接下來咱們試試自編寫一個新的具體裝飾者類。
//將全部大寫字符轉爲小寫
class LowerCaseInputSteam(inputStream: InputStream) : FilterInputStream(inputStream){
override fun read(): Int {
val result = super.read()
if(result==-1) return result
else return Character.toLowerCase(result)
}
override fun read(b: ByteArray, off: Int, len: Int): Int {
val result = super.read(b, off, len)
for (i in off until off+result){
b[i] = Character.toLowerCase(b[i].toInt()).toByte()
}
return result
}
}
複製代碼
此處須要實現兩個方法,一個針對字節,一個針對字節組。
try {
var inputStream : InputStream =
LowerCaseInputSteam(BufferedInputStream(FileInputStream("手機文件路徑")))
c = inputStream.read()
while (c!! >0) {
stringBuffer?.append(c!!)
c = inputStream.read()
}
tv_textview.text = stringBuffer.toString()
}catch (e : IOException){
e.printStackTrace()
}
複製代碼
第一次寫關於源碼的東西,寫的很差的地方,多多提意見。
下一次我將寫代理模式,也會講到裝飾模式和代理模式的區別,和本章未提到的裝飾模式的透明性。
如下是我「設計模式系列」文章,歡迎你們關注留言投幣丟香蕉。