策略模式 是指有一定行動(dòng)內(nèi)容的相對(duì)穩(wěn)定的策略名稱剑梳。用比較易懂的話來(lái)說(shuō)就是苗傅,定義算法族捺球,分別封裝起來(lái)缸浦,讓它們之間可以互相替換。
(一)簡(jiǎn)介
1. 主要解決的問(wèn)題
在一個(gè)系統(tǒng)中氮兵,如果某個(gè)問(wèn)題有多種解決方案(即有多種相似算法的情況下)裂逐,如果使用if...else...
去控制這些算法的使用,會(huì)使得代碼變得冗長(zhǎng)及復(fù)雜化泣栈,因此卜高,會(huì)使得系統(tǒng)變的更復(fù)雜和難以維護(hù)。
如果將這些算法封裝成一個(gè)個(gè)的類秩霍,并且實(shí)現(xiàn)同一個(gè)接口篙悯,那么這些算法可以任意地被替換。
當(dāng)系統(tǒng)在運(yùn)行時(shí)铃绒,如果想改變某種行為或解決方法的話鸽照,只需要setter
相關(guān)的算法類即可,不用再通過(guò)if...else...
的判斷邏輯去決定使用哪個(gè)算法颠悬。這樣就可以使得代碼行數(shù)變得更少矮燎,代碼邏輯更清晰,使得代碼更具有可讀性赔癌。
2. 優(yōu)缺點(diǎn)
-
優(yōu)點(diǎn):
- 算法可以自由切換诞外;
- 避免使用多重條件判斷;
- 擴(kuò)展性良好灾票。
-
缺點(diǎn):
- 策略類會(huì)增多峡谊;
- 所有策略類都需要對(duì)外暴露。
3. 使用場(chǎng)景
使用策略模式時(shí)刊苍,主要考慮以下幾個(gè)場(chǎng)景:
- 如果系統(tǒng)中有許多類既们,而這些類之間的區(qū)別僅在于它們的算法不同,那么使用策略模式可以動(dòng)態(tài)地讓對(duì)象在多種算法中選擇一種正什;
- 如果系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種啥纸,那么使用策略模式可以更方便;
- 如果對(duì)象的某種行為中婴氮,有多重條件選擇語(yǔ)句斯棒,最好是選擇策略模式盾致。
(二)實(shí)現(xiàn)
為了更好的解釋策略模式,我們舉一個(gè)日常生活中常見的例子來(lái)說(shuō)明荣暮。
1. 需求說(shuō)明
某視頻網(wǎng)站正在播出一部熱門電視劇庭惜,但是,神坑的是渠驼,該視頻網(wǎng)站采取饑餓營(yíng)銷的方式蜈块,每周只更新幾集鉴腻。
為了更好的服務(wù)廣大消費(fèi)者(其實(shí)迷扇,是為了掏空看客老爺們口袋中的錢),該網(wǎng)站推出了“充會(huì)員爽哎,比別人更早擁有”的活動(dòng)蜓席。
網(wǎng)站規(guī)定:普通用戶每周只能看四集;VIP
用戶每周可以看六集课锌;SVIP
用戶每周可以看八集厨内。
那么,請(qǐng)你設(shè)計(jì)一個(gè)權(quán)限控制系統(tǒng)渺贤,以此來(lái)控制不同權(quán)限用戶的觀看集數(shù)雏胃。
2. 系統(tǒng)設(shè)計(jì)
根據(jù)上述的需求說(shuō)明,我們可以得出結(jié)論: 每位用戶都可以看視頻志鞍,唯一不同的是看的集數(shù)不一樣瞭亮。
基于該結(jié)論,我們可以認(rèn)為:每個(gè)對(duì)象(用戶)的活動(dòng)(看視頻)都是一樣的固棚,不同的是行為(看的集數(shù))不同统翩。那么,我們采用策略模式此洲,來(lái)設(shè)計(jì)這套權(quán)限控制系統(tǒng)厂汗。
通過(guò)上述分析,我們構(gòu)建一個(gè)Permission
接口呜师;三個(gè)不同的權(quán)限用戶娶桦,分別是NormalPermission
、VipPermission
汁汗、SvipPermission
衷畦,它們都實(shí)現(xiàn)了Permission
接口;另外碰酝,我們還需要一個(gè)使用了上述三種策略的類霎匈,暫且叫它WatchVideo
。
類圖如下:
3. 代碼實(shí)現(xiàn)
(1)構(gòu)建Permission
接口
/**
*
* 權(quán)限接口
* @author Levi
* @date 2021/7/24
*/
public interface Permission {
/**
* 校驗(yàn)權(quán)限送爸,返回可看劇集的集數(shù)
* @return
*/
int checkPermission();
}
(2)構(gòu)建三個(gè)不同權(quán)限的用戶
1. 普通用戶權(quán)限铛嘱,只可以看四集
/**
*
* 普通用戶權(quán)限
* @author Levi
* @date 2021/7/24
*/
public class NormalPermission implements Permission{
/**
* 普通用戶可以看四集
* @return
*/
@Override
public int checkPermission() {
System.out.println("普通用戶暖释,每周只可以看四集。");
return 4;
}
}
2. VIP用戶權(quán)限墨吓,可以看六集
/**
*
* VIP用戶權(quán)限
* @author Levi
* @date 2021/7/24
*/
public class VipPermission implements Permission{
/**
* VIP用戶可以看六集
* @return
*/
@Override
public int checkPermission() {
System.out.println("VIP用戶球匕,每周只可以看六集。");
return 6;
}
}
3. SVIP用戶權(quán)限帖烘,可以看八集
/**
*
* SVIP用戶權(quán)限
* @author Levi
* @date 2021/7/24
*/
public class SvipPermission implements Permission{
/**
* VIP用戶可以看八集
* @return
*/
@Override
public int checkPermission() {
System.out.println("SVIP用戶亮曹,每周只可以看八集。");
return 8;
}
}
(3)構(gòu)建使用類
在使用類中秘症,通過(guò)構(gòu)造器動(dòng)態(tài)實(shí)例化permission
接口照卦,以此達(dá)到通過(guò)一個(gè)方法調(diào)用多種算法的目的。
/**
*
* 看劇的行為
* @author Levi
* @date 2021/7/24
*/
public class WatchVideo {
//permission接口
private Permission permission;
/**
* 在WatchVideo的構(gòu)造器中乡摹,動(dòng)態(tài)實(shí)例化permission
* @param permission
*/
public WatchVideo(Permission permission) {
this.permission = permission;
}
/**
* 校驗(yàn)用戶權(quán)限役耕,返回可以看的集數(shù)
* @return
*/
public int excutePermission() {
return permission.checkPermission();
}
}
(4)測(cè)試
使用watchVideo
來(lái)查看當(dāng)它改變策略permission
時(shí)的結(jié)果變化。
/**
*
* 測(cè)試策略模式
* @author Levi
* @date 2021/7/24
*/
public class TestStrategy {
public static void main(String[] args) {
WatchVideo watchVideo;
//不同權(quán)限用戶
// watchVideo=new WatchVideo(new NormalPermission());
watchVideo=new WatchVideo(new VipPermission());
// watchVideo=new WatchVideo(new SvipPermission());
int result=watchVideo.excutePermission();
System.out.println(result);
}
}
打印結(jié)果: