策略模式(Strategy Pattern)使用了算法族,分別封裝起來遇绞,讓它們可以互相替換嗓奢,此模式讓算法的變化獨(dú)立于使用算法的客戶讼撒。這種類型的設(shè)計(jì)模式屬于行為型模式。
從上面的概念我們可以看得出來,策略模式主要有兩個(gè)角色:算法族和使用算法的客戶根盒。算法族表示一系列的動(dòng)作和操作钳幅,而使用算法的客戶就是執(zhí)行這些操作的主體。
最近王者榮耀大火炎滞,爭議不斷敢艰,突然想到用王者榮耀的例子解析一下正在學(xué)習(xí)的設(shè)計(jì)模式,學(xué)習(xí)和玩樂結(jié)合是最好的搭配厂榛,現(xiàn)在我就以王者榮耀為情景解釋分析策略模式的操作盖矫。
1. 創(chuàng)建算法族:英雄技能
王者榮耀中每個(gè)英雄都有一套技能,每個(gè)英雄所擁有的技能都不一樣击奶,比如狄仁杰可以施放令牌技能辈双,項(xiàng)羽有霸王斬技能,魯班七號(hào)有無敵沙嘴炮技能柜砾,按照J(rèn)ava的封裝湃望、抽象特性,我們可以把技能抽象為一個(gè)接口痰驱,每一種技能實(shí)體都可以調(diào)用useSkill()執(zhí)行技能证芭;
public interface SkillBehavior {
void useSkill(); //釋放技能
}
英雄的技能多種多樣,我們把每一種技能都封裝為一個(gè)技能類担映,實(shí)現(xiàn)統(tǒng)一的接口SkillBehavior废士,這里舉例介紹三種技能:
public class ArrowSkill implements SkillBehavior{
@Override
public void useSkill() {
System.out.println("釋放暗箭技能");
}
}
public class KnifeSkill implements SkillBehavior {
@Override
public void useSkill() {
System.out.println("釋放長刀技能");
}
}
public class GunSkill implements SkillBehavior {
@Override
public void useSkill() {
System.out.println("釋放手槍技能");
}
}
2. 創(chuàng)建使用算法族客戶:英雄
技能已經(jīng)封裝好了,還需要有使用技能的客戶蝇完,那就是英雄了官硝,每個(gè)英雄都有一個(gè)共性,那就是可以施放技能短蜕,我們就抽象封裝出一個(gè)英雄類氢架,每個(gè)英雄都持有一個(gè)技能對(duì)象,并可以調(diào)用performSkill()施放自己擁有的技能:
public abstract class Hero {
public SkillBehavior mBehavior;
public Hero(){
System.out.print("英雄出生 ");
}
public void performSkill(){
if(mBehavior != null){
mBehavior.useSkill();
}
}
public void setSkillBehavior(SkillBehavior behavior){
mBehavior = behavior;
}
}
英雄類封裝好了朋魔,這時(shí)就需要有具體的英雄了岖研,這里我們舉例了三位英雄,也是我比較熟悉的英雄:狄仁杰警检、項(xiàng)羽孙援、魯班七號(hào),每個(gè)英雄都須繼承自Hero類:
public class DiRenJie extends Hero {
public DiRenJie(){
super();
System.out.println("狄仁杰:代表法律制裁你...");
mBehavior = new ArrowSkill();
}
}
public class XiangYu extends Hero {
public XiangYu(){
super();
System.out.println("項(xiàng)羽:我命由我... ");
mBehavior = new KnifeSkill();
}
}
public class LuBanQiHao extends Hero {
public LuBanQiHao() {
super();
System.out.println("魯班七號(hào):魔法大師扇雕,智障250赃磨,@¥%*&¥#... ");
mBehavior = new GunSkill();
}
}
3. 算法族客戶使用算法:英雄施放技能
技能和英雄都準(zhǔn)備好了,這時(shí)候就要應(yīng)該開始施放技能了:
public class KingGorgeDemo {
public static void main(String[] args){
Hero mDi = new DiRenJie();
mDi.performSkill();
Hero mXiang = new XiangYu();
mXiang.performSkill();
Hero mLu = new LuBanQiHao();
mLu.performSkill();
}
}
我們來看看各位英雄的輸出:
英雄出生 狄仁杰:代表法律制裁你...
釋放暗箭技能
英雄出生 項(xiàng)羽:我命由我...
釋放長刀技能
英雄出生 魯班七號(hào):魔法大師洼裤,智障250邻辉,@¥%*&¥#
釋放手槍技能
4. 讓算法族可以互相替換:英雄可以動(dòng)態(tài)更換技能
在最開始策略模式的概念中有一句話:策略模式使用了算法族溪王,分別封裝起來,讓它們可以互相替換值骇∮猓互相替換是什么概念呢,假設(shè)狄仁杰令牌技能使用膩了吱瘩,想試一下魯班七號(hào)的霸王槍技能道伟,那只需要?jiǎng)討B(tài)地給狄仁杰這個(gè)英雄設(shè)置一個(gè)GunSkill技能,后面就可以釋放魯班七號(hào)的技能了使碾。大家可以發(fā)現(xiàn)在Hero里有一個(gè)方法setSkillBehavior()蜜徽。操作如下:
public class KingGorgeDemo {
public static void main(String[] args){
Hero mDi = new DiRenJie();
SkillBehavior gunSkill = new GunSkill();
mDi.setSkillBehavior(gunSkill);
mDi.performSkill();
}
}
這時(shí)候的輸出就是:
英雄出生 狄仁杰:代表法律制裁你...
釋放手槍技能
雖然這個(gè)例子有點(diǎn)不恰當(dāng),王者榮耀也不可能有這種操作票摇,這只是一個(gè)簡單的例子方便說明問題而已拘鞋。可以舉例一個(gè)實(shí)際場景:騰訊要推出狄仁杰的一項(xiàng)叫“神捕”的新技能矢门,那只需要再封裝一個(gè)執(zhí)行SkillBehavior接口的技能類SeizeSkill盆色,創(chuàng)建出SeizeSkill對(duì)象并設(shè)置給狄仁杰英雄對(duì)象,這時(shí)候釋放技能時(shí)就是新的神捕技能了祟剔。
5. 策略模式的特性
策略模式對(duì)于軟件開發(fā)來說是一種很好的設(shè)計(jì)模式隔躲,即英雄要替換技能時(shí)不用去改變英雄的類,技能和英雄互相獨(dú)立物延,不耦合宣旱,可以用下面的類圖表示策略模式的結(jié)構(gòu):
優(yōu)點(diǎn):1、算法可以自由切換叛薯。 2浑吟、避免使用多重條件判斷。 3案训、擴(kuò)展性良好买置。
適用的場景:
1粪糙、如果在一個(gè)系統(tǒng)里面有許多類强霎,它們之間的區(qū)別僅在于它們的行為,那么使用策略模式可以動(dòng)態(tài)地讓一個(gè)對(duì)象在許多行為中選擇一種行為蓉冈。
2城舞、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種。
3寞酿、如果一個(gè)對(duì)象有很多的行為家夺,如果不用恰當(dāng)?shù)哪J剑@些行為就只好使用多重的條件選擇語句來實(shí)現(xiàn)伐弹。
示例代碼戳這里拉馋。