從業(yè)務(wù)出發(fā),來談?wù)劜呗阅J?,清爽的飛起~
點(diǎn)擊上方藍(lán)色“程序猿DD”,選擇“設(shè)為星標(biāo)”
回復(fù)“資源”獲取獨(dú)家整理的學(xué)習(xí)資料!

作者 | 路易小七
在講策略模式之前,我們先看一個(gè)日常生活中的小例子:
package?strategy.examp02;
import?java.math.BigDecimal;
public?class?QuoteManager?{
????public?BigDecimal?quote(BigDecimal?originalPrice,String?customType){
????????if?("新客戶".equals(customType))?{
????????????System.out.println("抱歉!新客戶沒有折扣!");
????????????return?originalPrice;
????????}else?if?("老客戶".equals(customType))?{
????????????System.out.println("恭喜你!老客戶打9折!");
????????????originalPrice?=?originalPrice.multiply(new?BigDecimal(0.9)).setScale(2,BigDecimal.ROUND_HALF_UP);
????????????return?originalPrice;
????????}else?if("VIP客戶".equals(customType)){
????????????System.out.println("恭喜你!VIP客戶打8折!");
????????????originalPrice?=?originalPrice.multiply(new?BigDecimal(0.8)).setScale(2,BigDecimal.ROUND_HALF_UP);
????????????return?originalPrice;
????????}
????????//其他人員都是原價(jià)
????????return?originalPrice;
????}
}
package?strategy.examp02;
import?java.math.BigDecimal;
public?class?QuoteManagerImprove?{
????public?BigDecimal?quote(BigDecimal?originalPrice,?String?customType){
????????if?("新客戶".equals(customType))?{
????????????return?this.quoteNewCustomer(originalPrice);
????????}else?if?("老客戶".equals(customType))?{
????????????return?this.quoteOldCustomer(originalPrice);
????????}else?if("VIP客戶".equals(customType)){
????????????return?this.quoteVIPCustomer(originalPrice);
????????}
????????//其他人員都是原價(jià)
????????return?originalPrice;
????}
????/**
?????*?對(duì)VIP客戶的報(bào)價(jià)算法
?????*?@param?originalPrice?原價(jià)
?????*?@return?折后價(jià)
?????*/
????private?BigDecimal?quoteVIPCustomer(BigDecimal?originalPrice)?{
????????System.out.println("恭喜!VIP客戶打8折");
????????originalPrice?=?originalPrice.multiply(new?BigDecimal(0.8)).setScale(2,BigDecimal.ROUND_HALF_UP);
????????return?originalPrice;
????}
????/**
?????*?對(duì)老客戶的報(bào)價(jià)算法
?????*?@param?originalPrice?原價(jià)
?????*?@return?折后價(jià)
?????*/
????private?BigDecimal?quoteOldCustomer(BigDecimal?originalPrice)?{
????????System.out.println("恭喜!老客戶打9折");
????????originalPrice?=?originalPrice.multiply(new?BigDecimal(0.9)).setScale(2,BigDecimal.ROUND_HALF_UP);
????????return?originalPrice;
????}
????/**
?????*?對(duì)新客戶的報(bào)價(jià)算法
?????*?@param?originalPrice?原價(jià)
?????*?@return?折后價(jià)
?????*/
????private?BigDecimal?quoteNewCustomer(BigDecimal?originalPrice)?{
????????System.out.println("抱歉!新客戶沒有折扣!");
????????return?originalPrice;
????}
}
對(duì)于擴(kuò)展是開放的(Open for extension)。這意味著模塊的行為是可以擴(kuò)展的。當(dāng)應(yīng)用的需求改變時(shí),我們可以對(duì)模塊進(jìn)行擴(kuò)展,使其具有滿足那些改變的新行為。也就是說,我們可以改變模塊的功能。
對(duì)于修改是關(guān)閉的(Closed for modification)。對(duì)模塊行為進(jìn)行擴(kuò)展時(shí),不必改動(dòng)模塊的源代碼或者二進(jìn)制代碼。
定義:
結(jié)構(gòu):
策略接口角色I(xiàn)Strategy:用來約束一系列具體的策略算法,策略上下文角色ConcreteStrategy使用此策略接口來調(diào)用具體的策略所實(shí)現(xiàn)的算法。
具體策略實(shí)現(xiàn)角色ConcreteStrategy:具體的策略實(shí)現(xiàn),即具體的算法實(shí)現(xiàn)。
策略上下文角色StrategyContext:策略上下文,負(fù)責(zé)和具體的策略實(shí)現(xiàn)交互,通常策略上下文對(duì)象會(huì)持有一個(gè)真正的策略實(shí)現(xiàn)對(duì)象,策略上下文還可以讓具體的策略實(shí)現(xiàn)從其中獲取相關(guān)數(shù)據(jù),回調(diào)策略上下文對(duì)象的方法。
UML類圖:

UML序列圖:

package?strategy.examp01;
//策略接口
public?interface?IStrategy?{
????//定義的抽象算法方法?來約束具體的算法實(shí)現(xiàn)方法
????public?void?algorithmMethod();
}
package?strategy.examp01;
//?具體的策略實(shí)現(xiàn)
public?class?ConcreteStrategy?implements?IStrategy?{
????//具體的算法實(shí)現(xiàn)
????@Override
????public?void?algorithmMethod()?{
????????System.out.println("this?is?ConcreteStrategy?method...");
????}
}
package?strategy.examp01;
?//?具體的策略實(shí)現(xiàn)2
public?class?ConcreteStrategy2?implements?IStrategy?{
?????//具體的算法實(shí)現(xiàn)
????@Override
????public?void?algorithmMethod()?{
????????System.out.println("this?is?ConcreteStrategy2?method...");
????}
}
package?strategy.examp01;
/**
?*?策略上下文
?*/
public?class?StrategyContext?{
????//持有一個(gè)策略實(shí)現(xiàn)的引用
????private?IStrategy?strategy;
????//使用構(gòu)造器注入具體的策略類
????public?StrategyContext(IStrategy?strategy)?{
????????this.strategy?=?strategy;
????}
????public?void?contextMethod(){
????????//調(diào)用策略實(shí)現(xiàn)的方法
????????strategy.algorithmMethod();
????}
}
package?strategy.examp01;
//外部客戶端
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????//1.創(chuàng)建具體測(cè)策略實(shí)現(xiàn)
????????IStrategy?strategy?=?new?ConcreteStrategy2();
????????//2.在創(chuàng)建策略上下文的同時(shí),將具體的策略實(shí)現(xiàn)對(duì)象注入到策略上下文當(dāng)中
????????StrategyContext?ctx?=?new?StrategyContext(strategy);
????????//3.調(diào)用上下文對(duì)象的方法來完成對(duì)具體策略實(shí)現(xiàn)的回調(diào)
????????ctx.contextMethod();
????}
}
package?strategy.examp02;
import?java.math.BigDecimal;
//報(bào)價(jià)策略接口
public?interface?IQuoteStrategy?{
????//獲取折后價(jià)的價(jià)格
????BigDecimal?getPrice(BigDecimal?originalPrice);
}
package?strategy.examp02;
import?java.math.BigDecimal;
//新客戶的報(bào)價(jià)策略實(shí)現(xiàn)類
public?class?NewCustomerQuoteStrategy?implements?IQuoteStrategy?{
????@Override
????public?BigDecimal?getPrice(BigDecimal?originalPrice)?{
????????System.out.println("抱歉!新客戶沒有折扣!");
????????return?originalPrice;
????}
}
package?strategy.examp02;
import?java.math.BigDecimal;
//老客戶的報(bào)價(jià)策略實(shí)現(xiàn)
public?class?OldCustomerQuoteStrategy?implements?IQuoteStrategy?{
????@Override
????public?BigDecimal?getPrice(BigDecimal?originalPrice)?{
????????System.out.println("恭喜!老客戶享有9折優(yōu)惠!");
????????originalPrice?=?originalPrice.multiply(new?BigDecimal(0.9)).setScale(2,BigDecimal.ROUND_HALF_UP);
????????return?originalPrice;
????}
}
package?strategy.examp02;
import?java.math.BigDecimal;
//VIP客戶的報(bào)價(jià)策略實(shí)現(xiàn)
public?class?VIPCustomerQuoteStrategy?implements?IQuoteStrategy?{
????@Override
????public?BigDecimal?getPrice(BigDecimal?originalPrice)?{
????????System.out.println("恭喜!VIP客戶享有8折優(yōu)惠!");
????????originalPrice?=?originalPrice.multiply(new?BigDecimal(0.8)).setScale(2,BigDecimal.ROUND_HALF_UP);
????????return?originalPrice;
????}
}
package?strategy.examp02;
import?java.math.BigDecimal;
//報(bào)價(jià)上下文角色
public?class?QuoteContext?{
????//持有一個(gè)具體的報(bào)價(jià)策略
????private?IQuoteStrategy?quoteStrategy;
????//注入報(bào)價(jià)策略
????public?QuoteContext(IQuoteStrategy?quoteStrategy){
????????this.quoteStrategy?=?quoteStrategy;
????}
????//回調(diào)具體報(bào)價(jià)策略的方法
????public?BigDecimal?getPrice(BigDecimal?originalPrice){
????????return?quoteStrategy.getPrice(originalPrice);
????}
}
package?strategy.examp02;
import?java.math.BigDecimal;
//外部客戶端
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????//1.創(chuàng)建老客戶的報(bào)價(jià)策略
????????IQuoteStrategy?oldQuoteStrategy?=?new?OldCustomerQuoteStrategy();
????????//2.創(chuàng)建報(bào)價(jià)上下文對(duì)象,并設(shè)置具體的報(bào)價(jià)策略
????????QuoteContext?quoteContext?=?new?QuoteContext(oldQuoteStrategy);
????????//3.調(diào)用報(bào)價(jià)上下文的方法
????????BigDecimal?price?=?quoteContext.getPrice(new?BigDecimal(100));
????????System.out.println("折扣價(jià)為:"?+price);
????}
}
恭喜!老客戶享有9折優(yōu)惠!
折扣價(jià)為:90.00
package?strategy.examp02;
import?java.math.BigDecimal;
//MVP客戶的報(bào)價(jià)策略實(shí)現(xiàn)
public?class?MVPCustomerQuoteStrategy?implements?IQuoteStrategy?{
????@Override
????public?BigDecimal?getPrice(BigDecimal?originalPrice)?{
????????System.out.println("哇偶!MVP客戶享受7折優(yōu)惠!??!");
????????originalPrice?=?originalPrice.multiply(new?BigDecimal(0.7)).setScale(2,BigDecimal.ROUND_HALF_UP);
????????return?originalPrice;
????}
}
package?strategy.examp02;
import?java.math.BigDecimal;
//外部客戶端
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????//創(chuàng)建MVP客戶的報(bào)價(jià)策略
????????IQuoteStrategy?mvpQuoteStrategy?=?new?MVPCustomerQuoteStrategy();
????????//創(chuàng)建報(bào)價(jià)上下文對(duì)象,并設(shè)置具體的報(bào)價(jià)策略
????????QuoteContext?quoteContext?=?new?QuoteContext(mvpQuoteStrategy);
????????//調(diào)用報(bào)價(jià)上下文的方法
????????BigDecimal?price?=?quoteContext.getPrice(new?BigDecimal(100));
????????System.out.println("折扣價(jià)為:"?+price);
????}
}
哇偶!MVP客戶享受7折優(yōu)惠?。?!
折扣價(jià)為:70.00
深入理解策略模式:
策略模式的作用:就是把具體的算法實(shí)現(xiàn)從業(yè)務(wù)邏輯中剝離出來,成為一系列獨(dú)立算法類,使得它們可以相互替換。
策略模式的著重點(diǎn):不是如何來實(shí)現(xiàn)算法,而是如何組織和調(diào)用這些算法,從而讓我們的程序結(jié)構(gòu)更加的靈活、可擴(kuò)展。
上策:挑選精兵,晝夜兼行直接偷襲成都,可以一舉而定,此為上計(jì)計(jì)也。 中策:楊懷、高沛是蜀中名將,手下有精銳部隊(duì),而且據(jù)守關(guān)頭,我們可以裝作要回荊州,引他們輕騎來見,可就此將其擒殺,而后進(jìn)兵成都,此為中計(jì)。 下策:退還白帝,連引荊州,慢慢進(jìn)圖益州,此為下計(jì)。
//攻取西川的策略
public?interface?IOccupationStrategyWestOfSiChuan?{
????public?void?occupationWestOfSiChuan(String?msg);
}
//攻取西川的上上計(jì)策
public?class?UpperStrategy?implements?IOccupationStrategyWestOfSiChuan?{
????@Override
????public?void?occupationWestOfSiChuan(String?msg)?{
????????if?(msg?==?null?||?msg.length()?5)?{
????????????//故意設(shè)置障礙,導(dǎo)致上上計(jì)策失敗
????????????System.out.println("由于計(jì)劃泄露,上上計(jì)策失?。?);
????????????int?i?=?100/0;
????????}
????????System.out.println("挑選精兵,晝夜兼行直接偷襲成都,可以一舉而定,此為上計(jì)計(jì)也!");
????}
}
//攻取西川的中計(jì)策
public?class?MiddleStrategy?implements?IOccupationStrategyWestOfSiChuan?{
????@Override
????public?void?occupationWestOfSiChuan(String?msg)?{
????????System.out.println("楊懷、高沛是蜀中名將,手下有精銳部隊(duì),而且據(jù)守關(guān)頭,我們可以裝作要回荊州,引他們輕騎來見,可就此將其擒殺,而后進(jìn)兵成都,此為中計(jì)。");
????}
}
//攻取西川的下計(jì)策
public?class?LowerStrategy?implements?IOccupationStrategyWestOfSiChuan?{
????@Override
????public?void?occupationWestOfSiChuan(String?msg)?{
????????System.out.println("退還白帝,連引荊州,慢慢進(jìn)圖益州,此為下計(jì)。");
????}
}
//攻取西川參謀部,就是上下文啦,由上下文來選擇具體的策略
public?class?OccupationContext??{
????public?void?occupationWestOfSichuan(String?msg){
????????//先用上上計(jì)策
????????IOccupationStrategyWestOfSiChuan?strategy?=?new?UpperStrategy();
????????try?{
????????????strategy.occupationWestOfSiChuan(msg);
????????}?catch?(Exception?e)?{
????????????//上上計(jì)策有問題行不通之后,用中計(jì)策
????????????strategy?=?new?MiddleStrategy();
????????????strategy.occupationWestOfSiChuan(msg);
????????}
????}
}
//此時(shí)外部客戶端相當(dāng)于劉備了,不管具體采用什么計(jì)策,只要結(jié)果(成功的攻下西川)
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????OccupationContext?context?=?new??OccupationContext();
????????//這個(gè)給手下的人激勵(lì)不夠啊
????????context.occupationWestOfSichuan("拿下西川");
????????System.out.println("=========================");
????????//這個(gè)人人有賞,讓士兵有動(dòng)力啊
????????context.occupationWestOfSichuan("拿下西川之后,人人有賞!");
????}
}
由于計(jì)劃泄露,上上計(jì)策失??!
楊懷、高沛是蜀中名將,手下有精銳部隊(duì),而且據(jù)守關(guān)頭,我們可以裝作要回荊州,引他們輕騎來見,可就此將其擒殺,而后進(jìn)兵成都,此為中計(jì)。
=========================
挑選精兵,晝夜兼行直接偷襲成都,可以一舉而定,此為上計(jì)計(jì)也!
策略和上下文的關(guān)系:
//支付策略接口
public?interface?PayStrategy?{
????//在支付策略接口的支付方法中含有支付上下文作為參數(shù),以便在具體的支付策略中回調(diào)上下文中的方法獲取數(shù)據(jù)
????public?void?pay(PayContext?ctx);
}
//人民幣支付策略
public?class?RMBPay?implements?PayStrategy?{
????@Override
????public?void?pay(PayContext?ctx)?{
????????System.out.println("現(xiàn)在給:"+ctx.getUsername()+"?人民幣支付?"+ctx.getMoney()+"元!");
????}
}
//美金支付策略
public?class?DollarPay?implements?PayStrategy?{
????@Override
????public?void?pay(PayContext?ctx)?{
????????System.out.println("現(xiàn)在給:"+ctx.getUsername()+"?美金支付?"+ctx.getMoney()+"dollar?!");
????}
}
//支付上下文,含有多個(gè)算法的公有數(shù)據(jù)
public?class?PayContext?{
????//員工姓名
????private?String?username;
????//員工的工資
????private?double?money;
????//支付策略
????private?PayStrategy?payStrategy;
????public?void?pay(){
????????//調(diào)用具體的支付策略來進(jìn)行支付
????????payStrategy.pay(this);
????}
????public?PayContext(String?username,?double?money,?PayStrategy?payStrategy)?{
????????this.username?=?username;
????????this.money?=?money;
????????this.payStrategy?=?payStrategy;
????}
????public?String?getUsername()?{
????????return?username;
????}
????public?double?getMoney()?{
????????return?money;
????}
}
//外部客戶端
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????//創(chuàng)建具體的支付策略
????????PayStrategy?rmbStrategy?=?new?RMBPay();
????????PayStrategy?dollarStrategy?=?new?DollarPay();
????????//準(zhǔn)備小王的支付上下文
????????PayContext?ctx?=?new?PayContext("小王",30000,rmbStrategy);
????????//向小王支付工資
????????ctx.pay();
????????//準(zhǔn)備Jack的支付上下文
????????ctx?=?new?PayContext("jack",10000,dollarStrategy);
????????//向Jack支付工資
????????ctx.pay();
????}
}
現(xiàn)在給:小王?人民幣支付 30000.0元!
現(xiàn)在給:jack 美金支付 10000.0dollar !
//銀行賬戶支付
public?class?AccountPay?implements?PayStrategy?{
????@Override
????public?void?pay(PayContext?ctx)?{
????????PayContextWithAccount?ctxAccount?=?(PayContextWithAccount)?ctx;
????????System.out.println("現(xiàn)在給:"+ctxAccount.getUsername()+"的賬戶:"+ctxAccount.getAccount()+"?支付工資:"+ctxAccount.getMoney()+"?元!");
????}
}
//帶銀行賬戶的支付上下文
public?class?PayContextWithAccount?extends?PayContext?{
????//銀行賬戶
????private?String?account;
????public?PayContextWithAccount(String?username,?double?money,?PayStrategy?payStrategy,String?account)?{
????????super(username,?money,?payStrategy);
????????this.account?=?account;
????}
????public?String?getAccount()?{
????????return?account;
????}
}
//外部客戶端
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????//創(chuàng)建具體的支付策略
????????PayStrategy?rmbStrategy?=?new?RMBPay();
????????PayStrategy?dollarStrategy?=?new?DollarPay();
????????//準(zhǔn)備小王的支付上下文
????????PayContext?ctx?=?new?PayContext("小王",30000,rmbStrategy);
????????//向小王支付工資
????????ctx.pay();
????????//準(zhǔn)備Jack的支付上下文
????????ctx?=?new?PayContext("jack",10000,dollarStrategy);
????????//向Jack支付工資
????????ctx.pay();
????????//創(chuàng)建支付到銀行賬戶的支付策略
????????PayStrategy?accountStrategy?=?new?AccountPay();
????????//準(zhǔn)備帶有銀行賬戶的上下文
????????ctx?=?new?PayContextWithAccount("小張",40000,accountStrategy,"1234567890");
????????//向小張的賬戶支付
????????ctx.pay();
????}
}
現(xiàn)在給:小王?人民幣支付 30000.0元!
現(xiàn)在給:jack 美金支付 10000.0dollar !
現(xiàn)在給:小張的賬戶:1234567890?支付工資:40000.0?元!
//支付到銀行賬戶的策略
public?class?AccountPay2?implements?PayStrategy?{
????//銀行賬戶
????private?String?account;
????public?AccountPay2(String?account)?{
????????this.account?=?account;
????}
????@Override
????public?void?pay(PayContext?ctx)?{
????????System.out.println("現(xiàn)在給:"+ctx.getUsername()+"的賬戶:"+getAccount()+"?支付工資:"+ctx.getMoney()+"?元!");
????}
????public?String?getAccount()?{
????????return?account;
????}
????public?void?setAccount(String?account)?{
????????this.account?=?account;
????}
}
//外部客戶端
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????//創(chuàng)建具體的支付策略
????????PayStrategy?rmbStrategy?=?new?RMBPay();
????????PayStrategy?dollarStrategy?=?new?DollarPay();
????????//準(zhǔn)備小王的支付上下文
????????PayContext?ctx?=?new?PayContext("小王",30000,rmbStrategy);
????????//向小王支付工資
????????ctx.pay();
????????//準(zhǔn)備Jack的支付上下文
????????ctx?=?new?PayContext("jack",10000,dollarStrategy);
????????//向Jack支付工資
????????ctx.pay();
????????//創(chuàng)建支付到銀行賬戶的支付策略
????????PayStrategy?accountStrategy?=?new?AccountPay2("1234567890");
????????//準(zhǔn)備上下文
????????ctx?=?new?PayContext("小張",40000,accountStrategy);
????????//向小張的賬戶支付
????????ctx.pay();
????}
}
現(xiàn)在給:小王?人民幣支付 30000.0元!
現(xiàn)在給:jack 美金支付 10000.0dollar !
現(xiàn)在給:小張的賬戶:1234567890?支付工資:40000.0?元!
優(yōu)點(diǎn):具體的策略實(shí)現(xiàn)風(fēng)格很是統(tǒng)一,策略實(shí)現(xiàn)所需要的數(shù)據(jù)都是從上下文中獲取的,在上下文中添加的數(shù)據(jù),可以視為公共的數(shù)據(jù),其他的策略實(shí)現(xiàn)也可以使用。
缺點(diǎn):很明顯如果某些數(shù)據(jù)只是特定的策略實(shí)現(xiàn)需要,大部分的策略實(shí)現(xiàn)不需要,那這些數(shù)據(jù)有“浪費(fèi)”之嫌,另外如果每次添加算法數(shù)據(jù)都擴(kuò)展上下文,很容易導(dǎo)致上下文的層級(jí)很是復(fù)雜。
優(yōu)點(diǎn):容易想到,實(shí)現(xiàn)簡(jiǎn)單
缺點(diǎn):與其他的策略實(shí)現(xiàn)風(fēng)格不一致,其他的策略實(shí)現(xiàn)所需數(shù)據(jù)都是來自上下文,而這個(gè)策略實(shí)現(xiàn)一部分?jǐn)?shù)據(jù)來自于自身,一部分?jǐn)?shù)據(jù)來自于上下文;外部在使用這個(gè)策略實(shí)現(xiàn)的時(shí)候也和其他的策略實(shí)現(xiàn)不一致了,難以以一個(gè)統(tǒng)一的方式動(dòng)態(tài)的切換策略實(shí)現(xiàn)。
策略模式在JDK中的應(yīng)用:
public?ThreadPoolExecutor(int?corePoolSize,
??????????????????????????????int?maximumPoolSize,
??????????????????????????????long?keepAliveTime,
??????????????????????????????TimeUnit?unit,
??????????????????????????????BlockingQueue?workQueue, ?{
??????????????????????????????ThreadFactory?threadFactory,
??????????????????????????????RejectedExecutionHandler?handler)
????????if?(corePoolSize?0?||
????????????maximumPoolSize?<=?0?||
????????????maximumPoolSize?????????????keepAliveTime?0)
????????????throw?new?IllegalArgumentException();
????????if?(workQueue?==?null?||?threadFactory?==?null?||?handler?==?null)
????????????throw?new?NullPointerException();
????????this.corePoolSize?=?corePoolSize;
????????this.maximumPoolSize?=?maximumPoolSize;
????????this.workQueue?=?workQueue;
????????this.keepAliveTime?=?unit.toNanos(keepAliveTime);
????????this.threadFactory?=?threadFactory;
????????this.handler?=?handler;
????}
corePoolSize:線程池中的核心線程數(shù)量,即使這些線程沒有任務(wù)干,也不會(huì)將其銷毀。 maximumPoolSize:線程池中的最多能夠創(chuàng)建的線程數(shù)量。 keepAliveTime:當(dāng)線程池中的線程數(shù)量大于corePoolSize時(shí),多余的線程等待新任務(wù)的最長(zhǎng)時(shí)間。 unit:keepAliveTime的時(shí)間單位。 workQueue:在線程池中的線程還沒有還得及執(zhí)行任務(wù)之前,保存任務(wù)的隊(duì)列(當(dāng)線程池中的線程都有任務(wù)在執(zhí)行的時(shí)候,仍然有任務(wù)不斷的提交過來,這些任務(wù)保存在workQueue隊(duì)列中)。 threadFactory:創(chuàng)建線程池中線程的工廠。 handler:當(dāng)線程池中沒有多余的線程來執(zhí)行任務(wù),并且保存任務(wù)的多列也滿了(指的是有界隊(duì)列),對(duì)仍在提交給線程池的任務(wù)的處理策略。
public?interface?RejectedExecutionHandler?{
????/**
?????*當(dāng)ThreadPoolExecutor的execut方法調(diào)用時(shí),并且ThreadPoolExecutor不能接受一個(gè)任務(wù)Task時(shí),該方法就有可能被調(diào)用。
???*?不能接受一個(gè)任務(wù)Task的原因:有可能是沒有多余的線程來處理,有可能是workqueue隊(duì)列中沒有多余的位置來存放該任務(wù),該方法有可能拋出一個(gè)未受檢的異常RejectedExecutionException
?????*?@param?r?the?runnable?task?requested?to?be?executed
?????*?@param?executor?the?executor?attempting?to?execute?this?task
?????*?@throws?RejectedExecutionException?if?there?is?no?remedy
?????*/
????void?rejectedExecution(Runnable?r,?ThreadPoolExecutor?executor);
}
該策略接口有四個(gè)實(shí)現(xiàn)類:
/**
?????*?A?handler?for?rejected?tasks?that?throws?a
?????*?RejectedExecutionException.
?????*/
????public?static?class?AbortPolicy?implements?RejectedExecutionHandler?{
????????/**
?????????*?Creates?an?AbortPolicy.
?????????*/
????????public?AbortPolicy()?{?}
????????/**
?????????*?Always?throws?RejectedExecutionException.
?????????*?@param?r?the?runnable?task?requested?to?be?executed
?????????*?@param?e?the?executor?attempting?to?execute?this?task
?????????*?@throws?RejectedExecutionException?always.
?????????*/
????????public?void?rejectedExecution(Runnable?r,?ThreadPoolExecutor?e)?{
????????????throw?new?RejectedExecutionException();
????????}
????}
/**
?????*?A?handler?for?rejected?tasks?that?silently?discards?the
?????*?rejected?task.
?????*/
????public?static?class?DiscardPolicy?implements?RejectedExecutionHandler?{
????????/**
?????????*?Creates?a?DiscardPolicy.
?????????*/
????????public?DiscardPolicy()?{?}
????????/**
?????????*?Does?nothing,?which?has?the?effect?of?discarding?task?r.
?????????*?@param?r?the?runnable?task?requested?to?be?executed
?????????*?@param?e?the?executor?attempting?to?execute?this?task
?????????*/
????????public?void?rejectedExecution(Runnable?r,?ThreadPoolExecutor?e)?{
????????}
????}
/**
?????*?A?handler?for?rejected?tasks?that?discards?the?oldest?unhandled
?????*?request?and?then?retries?execute,?unless?the?executor
?????*?is?shut?down,?in?which?case?the?task?is?discarded.
?????*/
????public?static?class?DiscardOldestPolicy?implements?RejectedExecutionHandler?{
????????/**
?????????*?Creates?a?DiscardOldestPolicy?for?the?given?executor.
?????????*/
????????public?DiscardOldestPolicy()?{?}
????????/**
?????????*?Obtains?and?ignores?the?next?task?that?the?executor
?????????*?would?otherwise?execute,?if?one?is?immediately?available,
?????????*?and?then?retries?execution?of?task?r,?unless?the?executor
?????????*?is?shut?down,?in?which?case?task?r?is?instead?discarded.
?????????*?@param?r?the?runnable?task?requested?to?be?executed
?????????*?@param?e?the?executor?attempting?to?execute?this?task
?????????*/
????????public?void?rejectedExecution(Runnable?r,?ThreadPoolExecutor?e)?{
????????????if?(!e.isShutdown())?{
????????????????e.getQueue().poll();
????????????????e.execute(r);
????????????}
????????}
????}
/**
?????*?A?handler?for?rejected?tasks?that?runs?the?rejected?task
?????*?directly?in?the?calling?thread?of?the?{@code?execute}?method,
?????*?unless?the?executor?has?been?shut?down,?in?which?case?the?task
?????*?is?discarded.
?????*/
????public?static?class?CallerRunsPolicy?implements?RejectedExecutionHandler?{
????????/**
?????????*?Creates?a?{@code?CallerRunsPolicy}.
?????????*/
????????public?CallerRunsPolicy()?{?}
????????/**
?????????*?Executes?task?r?in?the?caller's?thread,?unless?the?executor
?????????*?has?been?shut?down,?in?which?case?the?task?is?discarded.
?????????*
?????????*?@param?r?the?runnable?task?requested?to?be?executed
?????????*?@param?e?the?executor?attempting?to?execute?this?task
?????????*/
????????public?void?rejectedExecution(Runnable?r,?ThreadPoolExecutor?e)?{
????????????if?(!e.isShutdown())?{
????????????????r.run();
????????????}
????????}
????}

策略模式的優(yōu)點(diǎn):
策略模式的功能就是通過抽象、封裝來定義一系列的算法,使得這些算法可以相互替換,所以為這些算法定義一個(gè)公共的接口,以約束這些算法的功能實(shí)現(xiàn)。如果這些算法具有公共的功能,可以將接口變?yōu)槌橄箢?,將公共功能放到抽象父類里面?/section> 策略模式的一系列算法是可以相互替換的、是平等的,寫在一起就是if-else組織結(jié)構(gòu),如果算法實(shí)現(xiàn)里又有條件語(yǔ)句,就構(gòu)成了多重條件語(yǔ)句,可以用策略模式,避免這樣的多重條件語(yǔ)句。 擴(kuò)展性更好:在策略模式中擴(kuò)展策略實(shí)現(xiàn)非常的容易,只要新增一個(gè)策略實(shí)現(xiàn)類,然后在使用策略實(shí)現(xiàn)的地方,使用這個(gè)新的策略實(shí)現(xiàn)就好了。
策略模式的缺點(diǎn):
策略模式的本質(zhì):
往期推薦
我在星球與你分享經(jīng)驗(yàn)、交流成長(zhǎng)
???????



