回爐設計模式——策略模式
不要問我什麼是策略模式,也不要問我策略模式的要素,關鍵點是什麼?我希望這些問題,你能自己找到答案。當然,最後我還是會講的。
這是我寫的第一個設計模式,所以,避免枯燥乏味。我們先做一個小遊戲吧。
我們設計一款冒險動作的遊戲,就叫他“拯救公主”吧,小時候玩過很多類似的遊戲。就“抄襲”我們經典“超級瑪麗”吧。
開場,我們的公主被惡魔抓走了,,,需要勇士去營救。
我們準備進入遊戲了,首先是選擇主角(馬里奧,路易基,庫巴(目前就只提供3個吧)),我們就選馬里奧吧。
然後,馬里奧就踏上了營救公主的道路(此處省略一萬字)。
最後,馬里奧終於走到了關押公主的城堡,但是,這裡有3個強大的敵人(暫時就設計3個吧)。他們,是“怕火”,“怕水”,“怕電”,
講到這裡,聰明的小夥伴肯定猜到,要打敗這三個敵人要分別用火,水,電了吧。
沒錯,當馬里奧對戰“怕火”的時候要用“火焰攻擊”,對戰“怕水”的時候要用“水攻擊”,遇到“怕電”的時候,要用“電攻擊”。
最後,由於馬里奧採用了正確的攻擊策略,所以,馬里奧成功的救了公主,並和公主開心的在一起了。
故事講完了,我們來設計程式怎麼寫吧:
你可能會說,這個簡單:像下面這樣,建立一個馬里奧類,他有三個方法:火攻擊,水攻擊,電攻擊。就可以實現上面的“打敵人”遊戲了。

我:那還有兩個角色怎麼辦呢?
你:這個也簡單呀,我寫一個抽象類,馬里奧,路易基,庫巴都繼承這個類,然後,把這3個方法放到抽象類就可以了:

我:嗯,這樣挺好的,每個具體角色都只需要實現role的方法,就可以實現我們的需求了,而且如果再加入新的角色,只需要繼承這個role就可以了。很棒哦,但是,如果我們加入一個新的角色“耀西”,但是這個耀西不會火焰攻擊,卻多會一種”風攻擊“,該怎麼辦呢?
你:。。。這個,還能有這種情況?
我:當然,,那這個時候是不是要再改改?
你:那就這樣:把各種攻擊,改為介面,實現一個介面,就擁有一種攻擊,這樣,就可以實現你說的那種情況了。

我:這樣,的確可以解決角色之間擁有不同攻擊手段的問題,那麼又有問題了,如果,現在有幾十上百中攻擊手段,而某些角色又擁有很多種攻擊手段,那豈不是些角色,要實現很多介面,,,這實在不太好吧。
你:那該怎麼辦呀?我實在沒辦法了。
我:我們可以這樣改:抽象父類Role種,定義一個攻擊手段的集合,一個抽象攻擊方法,一個新增攻擊手段的方法。
子類只需要實現攻擊方法。另外一邊,定義一個攻擊手段的介面,然後,他有很多的具體實現。這樣就實現了一種很優的解決方案。
我們來試一下,馬裡
奧會火焰攻擊,耀西會風攻擊,庫巴會水攻擊和電攻擊。那麼,就是這樣寫:
Attack fire = new Fire()
Attack water= new Water()
Attack wind= new Wind()
Attack elec= new Electric()
Role maliao = new Bowser()
maliao.addAttack(fire)
Role yaoxi= new Yoshi()
yaoxi.addAttack(wind)
庫巴就省略了。
maliao.attack()
yaoxi.attack()

我:像這樣寫,就可以高度解耦攻擊手段和角色之間的關係依賴了。並且,攻擊手段之間可以相互替換,突然有一天,馬里奧會風攻擊了,那隻需要把風攻擊手段給他加上去就可以了,或者他不會攻擊了,那就把他的攻擊手段給去掉就可以了。
其實,策略模式核心思想就是行為替換(演算法替換),把一堆變化的演算法(行為)進行分類封裝,形成一個演算法族(行為族),同一個演算法族種的演算法可以彼此替換,這就是策略模式的核心。
當然,你看我的這個策略模式,和很多網上其他的解釋,例子可能會有不同。因為我是在一個時間例子(問題)中去講的,所以,其實,這並不是只有策略模式,我也並不想跟你說什麼是策略模式之類的,我只是想講策略模式的一種常用的用法,和對實際問題該怎麼思考。
最後囉嗦幾句,設計模式,是一種經驗,思想,是解決問題的一種思路。一定是有一個什麼樣的問題,然後用什麼方式(模式)解決,而不是,因為有一個什麼樣的模式,所以我要這樣去寫。千萬不要本末倒置。
還有,我有些地方沒有寫,也沒有講,希望你們能自己去思考,而不是,我全都告訴你,那樣並沒有什麼好處。我寫這個系列也是希望可以通過一些例子,引導你去思考,而不是為了學設計模式而學設計模式。