1.初識(shí)策略模式
定義一系列的算法,把它們一個(gè)個(gè)封裝起來,并且使它們可相互替換广凸。本模式使得算法可獨(dú)立于使用它的客戶而變化典鸡。
- Strategy:策略接口被廓,用來約束一系列具體的策略算法。Context使用這個(gè)接口來調(diào)用具體的策略實(shí)現(xiàn)定義的算法萝玷。
ConcreteStrategy:
具體的策略實(shí)現(xiàn)嫁乘,也就是具體的算法實(shí)現(xiàn)。
Context:上下文球碉,負(fù)責(zé)和具體的策略類交互蜓斧,通常上下文會(huì)持有一個(gè)真正的策略實(shí)現(xiàn),上下文還可以讓具體的策略類來獲取上下文的數(shù)據(jù)睁冬,甚至讓具體的策略類來回調(diào)上下文的方法挎春。
2.體會(huì)策略模式
2.1 場(chǎng)景問題——報(bào)價(jià)管理
向客戶報(bào)價(jià),對(duì)于銷售部門的人來講豆拨,這是一個(gè)非常重大直奋、非常復(fù)雜的問
題,對(duì)不同的客戶要報(bào)不同的價(jià)格施禾,比如:
- 1)對(duì)普通客戶或者是新客戶報(bào)的是全價(jià)
- 2)對(duì)老客戶報(bào)的價(jià)格脚线,根據(jù)客戶年限,給予一定的折扣
- 3)對(duì)大客戶報(bào)的價(jià)格弥搞,根據(jù)大客戶的累計(jì)消費(fèi)金額邮绿,給予一定的折扣
- 4)還要考慮客戶購買的數(shù)量和金額渠旁,比如:雖然是新用戶,但是一次購買的數(shù)量非常大斯碌,或者是總金額非常高一死,也會(huì)有一定的折扣
- 5)還有,報(bào)價(jià)人員的職務(wù)高低傻唾,也決定了他是否有權(quán)限對(duì)價(jià)格進(jìn)行一定的浮動(dòng)折扣
- 6)甚至在不同的階段投慈,對(duì)客戶的報(bào)價(jià)也不同,一般情況是剛開始比較高冠骄,越接近成交階段伪煤,報(bào)價(jià)越趨于合理。
總之凛辣,向客戶報(bào)價(jià)是非常復(fù)雜的抱既,因此在一些CRM(客戶關(guān)系管理)的系統(tǒng)中,會(huì)有一個(gè)單獨(dú)的報(bào)價(jià)管理模塊扁誓,來處理復(fù)雜的報(bào)價(jià)功能防泵。
為了演示的簡潔性,假定現(xiàn)在需要實(shí)現(xiàn)一個(gè)簡化的報(bào)價(jià)管理蝗敢,實(shí)現(xiàn)如下的功能:
- 1)對(duì)普通客戶或者是新客戶報(bào)全價(jià)
- 2)對(duì)老客戶報(bào)的價(jià)格捷泞,統(tǒng)一折扣5%
- 3)對(duì)大客戶報(bào)的價(jià)格,統(tǒng)一折扣10%
該怎么實(shí)現(xiàn)呢寿谴?
2.2 不用模式的解決方案
上面的寫法是很簡單的锁右,也很容易想,但是仔細(xì)想想讶泰,這樣實(shí)現(xiàn)咏瑟,問題可不小,比如:
第一個(gè)問題:價(jià)格類包含了所有計(jì)算報(bào)價(jià)的算法痪署,使得價(jià)格類码泞,尤其是報(bào)價(jià)這個(gè)方法比較龐雜,難以維護(hù)狼犯。
第二個(gè)問題:經(jīng)常會(huì)有這樣的需要余寥,在不同的時(shí)候,要使用不同的計(jì)算方式辜王。
那么到底應(yīng)該如何實(shí)現(xiàn),才能夠讓價(jià)格類中的計(jì)算報(bào)價(jià)的算法罐孝,能很容易的實(shí)現(xiàn)可維護(hù)呐馆、可擴(kuò)展,又能動(dòng)態(tài)的切換變化呢莲兢?
2.3 使用模式的解決方案
2.3.1 使用模式來解決的思路
仔細(xì)分析上面的問題汹来,先來把它抽象一下续膳,各種計(jì)算報(bào)價(jià)的計(jì)算方式就好比是具體的算法,而使用這些計(jì)算方式來計(jì)算報(bào)價(jià)的程序收班,就相當(dāng)于是使用算法的客戶坟岔。
再分析上面的實(shí)現(xiàn)方式,為什么會(huì)造成那些問題摔桦,根本原因社付,就在于算法和使用算法的客戶是耦合的,甚至是密不可分的邻耕,在上面實(shí)現(xiàn)中鸥咖,具體的算法和使用算法的客戶是同一個(gè)類里面的不同方法。
現(xiàn)在要解決那些問題兄世,按照策略模式的方式啼辣,應(yīng)該先把所有的計(jì)算方式獨(dú)
立出來做成單獨(dú)的算法類。
然后引入上下文對(duì)象來實(shí)現(xiàn)具體的算法和直接使用算法的客戶是分離的御滩。
具體的算法和使用它的客戶分離過后鸥拧,使得算法可獨(dú)立于使用它的客戶而變化,并且能夠動(dòng)態(tài)的切換需要使用的算法削解,只要客戶端動(dòng)態(tài)的選擇不同的算法富弦,然后設(shè)置到上下文對(duì)象中去,實(shí)際調(diào)用的時(shí)候钠绍,就可以調(diào)用到不同的算法舆声。
2.3.2 使用模式的解決方案的類圖
3.理解策略模式
3.1 認(rèn)識(shí)策略模式
3.1.1 策略模式的功能
策略模式的功能是把具體的算法實(shí)現(xiàn),從具體的業(yè)務(wù)處理里面獨(dú)立出來柳爽,實(shí)現(xiàn)成為單獨(dú)的算法類媳握,從而形成一系列的算法,并讓這些算法可以相互替換磷脯。
策略模式的重心不是如何來實(shí)現(xiàn)算法蛾找,而是如何組織、調(diào)用這些算法赵誓,從而讓程序結(jié)構(gòu)更靈活打毛、具有更好的維護(hù)性和擴(kuò)展性
3.1.2 策略模式和if-else語句
看了前面的示例,很多朋友會(huì)發(fā)現(xiàn)俩功,每個(gè)策略算法具體實(shí)現(xiàn)的功能幻枉,就是原來在if-else結(jié)構(gòu)中的具體實(shí)現(xiàn)。沒錯(cuò)诡蜓,其實(shí)多個(gè)if-elseif語句表達(dá)的就是一個(gè)平等的功能結(jié)構(gòu)熬甫,你要么執(zhí)行if,要不你就執(zhí)行else蔓罚,或者是 elseif椿肩,這個(gè)時(shí)候瞻颂,if塊里面的實(shí)現(xiàn)和else塊里面的實(shí)現(xiàn)從運(yùn)行地位上來講就是平等的。
而策略模式就是把各個(gè)平等的具體實(shí)現(xiàn)封裝到單獨(dú)的策略實(shí)現(xiàn)類了郑象,然后通過上下文來與具體的策略類進(jìn)行交互贡这。因此多個(gè)if-else語句可以考慮使用策略模式
3.1.3 算法的平等性
策略模式一個(gè)很大的特點(diǎn)就是各個(gè)策略算法的平等性。對(duì)于一系列具體的策略算法厂榛,大家的地位是完全一樣的盖矫,正是因?yàn)檫@個(gè)平等性,才能實(shí)現(xiàn)算法之間可以相互替換噪沙。
所有的策略算法在實(shí)現(xiàn)上也是相互獨(dú)立的炼彪,相互之間是沒有依賴的。
所以可以這樣描述這一系列策略算法:策略算法是相同行為的不同實(shí)現(xiàn)正歼。
3.1.4 誰來選擇具體的策略算法
在策略模式中辐马,可以在兩個(gè)地方來進(jìn)行具體策略的選擇。
一個(gè)是在客戶端局义,在使用上下文的時(shí)候喜爷,由客戶端來選擇具體的策略算法,然后把這個(gè)策略算法設(shè)置給上下文萄唇。前面的示例就是這種情況檩帐。
還有一個(gè)是客戶端不管,由上下文來選擇具體的策略算法另萤,這個(gè)在后面講容錯(cuò)恢復(fù)的時(shí)候給大家演示一下湃密。
3.1.5 Strategy的實(shí)現(xiàn)方式
在前面的示例中,Strategy都是使用的接口來定義的四敞,這也是常見的實(shí)現(xiàn)
方式泛源。但是如果多個(gè)算法具有公共功能的話,可以把Strategy實(shí)現(xiàn)成為抽象類忿危,然后把多個(gè)算法的公共功能實(shí)現(xiàn)到Strategy里面达箍。
3.1.6 運(yùn)行時(shí)策略的唯一性
運(yùn)行期間,策略模式在每一個(gè)時(shí)刻只能使用一個(gè)具體的策略實(shí)現(xiàn)對(duì)象铺厨,雖然可以動(dòng)態(tài)的在不同的策略實(shí)現(xiàn)中切換缎玫,但是同時(shí)只能使用一個(gè)。
3.1.7 增加新的策略
在前面的示例里面解滓,體會(huì)到了策略模式中切換算法的方便赃磨,但是增加一個(gè)
新的算法會(huì)怎樣呢?比如現(xiàn)在要實(shí)現(xiàn)如下的功能:對(duì)于公司的“戰(zhàn)略合作客戶”洼裤,統(tǒng)一8折邻辉。
其實(shí)很簡單,策略模式可以讓你很靈活的擴(kuò)展新的算法。具體的做法是:
先寫一個(gè)策略算法類來實(shí)現(xiàn)新的要求恩沛,然后在客戶端使用的時(shí)候指定使用新的策略算法類就可以了。
3.1.8 策略模式調(diào)用順序示意圖
3.2 Context和Strategy的關(guān)系
在策略模式中缕减,通常是上下文使用具體的策略實(shí)現(xiàn)對(duì)象雷客,反過來,策略實(shí)
現(xiàn)對(duì)象也可以從上下文獲取所需要的數(shù)據(jù)桥狡,因此可以將上下文當(dāng)參數(shù)傳遞給策略實(shí)現(xiàn)對(duì)象搅裙,這種情況下上下文和策略實(shí)現(xiàn)對(duì)象是緊密耦合的。
在這種情況下裹芝,上下文封裝著具體策略對(duì)象進(jìn)行算法運(yùn)算所需要的數(shù)據(jù)部逮,具體策略對(duì)象通過回調(diào)上下文的方法來獲取這些數(shù)據(jù)。
甚至在某些情況下嫂易,策略實(shí)現(xiàn)對(duì)象還可以回調(diào)上下文的方法來實(shí)現(xiàn)一定的
功能兄朋,這種使用場(chǎng)景下,上下文變相充當(dāng)了多個(gè)策略算法實(shí)現(xiàn)的公共接口怜械,在上下文定義的方法可以當(dāng)做是所有或者是部分策略算法使用的公共功能颅和。
但是請(qǐng)注意,由于所有的策略實(shí)現(xiàn)對(duì)象都實(shí)現(xiàn)同一個(gè)策略接口缕允,傳入同一個(gè)上下文峡扩,可能會(huì)造成傳入的上下文數(shù)據(jù)的浪費(fèi),因?yàn)橛械乃惴〞?huì)使用這些數(shù)據(jù)障本,而有的算法不會(huì)使用教届,但是上下文和策略對(duì)象之間交互的開銷是存在的了。
3.3 工資支付的實(shí)現(xiàn)思路
隨著公司的發(fā)展驾霜,會(huì)不斷有新的工資支付方式出現(xiàn)案训,這就要求能方便的擴(kuò)展;另外工資支付方式不是固定的寄悯,要求能很方便的切換具體的支付方式萤衰。
要實(shí)現(xiàn)這樣的功能,策略模式是一個(gè)很好的選擇猜旬。在實(shí)現(xiàn)這個(gè)功能的時(shí)候脆栋,不同的策略算法需要的數(shù)據(jù)是不一樣,比如:現(xiàn)金支付就不需要銀行帳號(hào)洒擦,而銀行轉(zhuǎn)賬就需要帳號(hào)椿争。這就導(dǎo)致在設(shè)計(jì)策略接口中的方法時(shí),不太好確定參數(shù)的個(gè)數(shù)熟嫩,而且秦踪,就算現(xiàn)在把所有的參數(shù)都列上了,今后擴(kuò)展呢?難道再來修改策略接口嗎椅邓?如果這樣做柠逞,那無異于一場(chǎng)災(zāi)難,加入一個(gè)新策略景馁,就需要修改接口板壮,然后修改所有已有的實(shí)現(xiàn),不瘋掉才怪合住!那么到底如何實(shí)現(xiàn)绰精,在今后擴(kuò)展的時(shí)候才最方便呢?
解決方案之一透葛,就是把上下文當(dāng)做參數(shù)傳遞給策略對(duì)象笨使,這樣一來,如果要擴(kuò)展新的策略實(shí)現(xiàn)僚害,只需要擴(kuò)展上下文就可以了硫椰,已有的實(shí)現(xiàn)不需要做任何的修改。
現(xiàn)在有這么兩種擴(kuò)展的實(shí)現(xiàn)方式萨蚕,到底使用哪一種呢最爬?或者是哪種實(shí)現(xiàn)更好呢?下面來比較一下:
- 1)對(duì)于擴(kuò)展上下文的方式:這樣實(shí)現(xiàn)门岔,所有策略的實(shí)現(xiàn)風(fēng)格更統(tǒng)一爱致,策略需要的數(shù)據(jù)都統(tǒng)一從上下文來獲取,這樣在使用方法上也很統(tǒng)一寒随;另外糠悯,在上下文中添加新的數(shù)據(jù),別的相應(yīng)算法也可以用得上妻往,可以視為公共的數(shù)據(jù)互艾。但缺點(diǎn)也很明顯,如果這些數(shù)據(jù)只有一個(gè)特定的算法來使用讯泣,那么這些數(shù)據(jù)有些浪費(fèi)纫普;另外每次添加新的算法都去擴(kuò)展上下文,容易形成復(fù)雜的上下文對(duì)象層次好渠,也未見得有必要昨稼。
- 2)對(duì)于在策略算法的實(shí)現(xiàn)上添加自己需要的數(shù)據(jù)的方式:這樣實(shí)現(xiàn),比較好想拳锚,實(shí)現(xiàn)簡單假栓。但是缺點(diǎn)也很明顯,跟其它策略實(shí)現(xiàn)的風(fēng)格不一致霍掺,其它策略都是從上下文中來獲取數(shù)據(jù)匾荆,而這個(gè)策略的實(shí)現(xiàn)一部分?jǐn)?shù)據(jù)來自上下文拌蜘,一部分?jǐn)?shù)據(jù)來自自己,有些不統(tǒng)一牙丽;另外简卧,這樣一來,外部使用這些策略算法的時(shí)候也不一樣了烤芦,不太好以一個(gè)統(tǒng)一的方式來動(dòng)態(tài)切換策略算法贞滨。
兩種實(shí)現(xiàn)各有優(yōu)劣,至于如何選擇拍棕,那就具體問題,具體的分析了勺良。
3.4 另一種策略模式調(diào)用順序示意圖
策略模式調(diào)用還有一種情況绰播,就是把Context當(dāng)做參數(shù)來傳遞給Strategy,也就是本例示范的這種方式尚困,這個(gè)時(shí)候策略模式的調(diào)用順序如圖
3.5 容錯(cuò)恢復(fù)機(jī)制
容錯(cuò)恢復(fù)機(jī)制是應(yīng)用程序開發(fā)中非常常見的功能蠢箩。什么是容錯(cuò)恢復(fù)呢?簡單點(diǎn)說就是:程序運(yùn)行的時(shí)候事甜,正常情況下應(yīng)該按照某種方式來做谬泌,如果按照某種方式來做發(fā)生錯(cuò)誤的話,系統(tǒng)并不會(huì)崩潰逻谦,也不會(huì)就此不能繼續(xù)向下運(yùn)行了掌实,而是有容忍出錯(cuò)的能力,不但能容忍程序運(yùn)行出現(xiàn)錯(cuò)誤邦马,還提供出現(xiàn)錯(cuò)誤后的備用方案贱鼻,也就是恢復(fù)機(jī)制,來代替正常執(zhí)行的功能滋将,使程序繼續(xù)向下運(yùn)行邻悬。
舉個(gè)實(shí)際點(diǎn)的例子吧,比如在一個(gè)系統(tǒng)中随闽,所有對(duì)系統(tǒng)的操作都要有日志記錄父丰,而且這個(gè)日志還需要有管理界面,這種情況下通常會(huì)把日志記錄在數(shù)據(jù)庫里面掘宪,方便后續(xù)的管理蛾扇,但是在記錄日志到數(shù)據(jù)庫的時(shí)候,可能會(huì)發(fā)生錯(cuò)誤魏滚,比如暫時(shí)連不上數(shù)據(jù)庫了屁桑,那就先記錄在文件里面,然后在合適的時(shí)候把文件中的記錄再轉(zhuǎn)錄到數(shù)據(jù)庫中栏赴。
對(duì)于這樣的功能蘑斧,就可以采用策略模式,把日志記錄到數(shù)據(jù)庫和日志記錄到文件當(dāng)作兩種記錄日志的策略,然后在運(yùn)行期間根據(jù)需要進(jìn)行動(dòng)態(tài)的切換
3.6 策略模式結(jié)合模板方法模式
在實(shí)際應(yīng)用策略模式的過程中竖瘾,經(jīng)常會(huì)出現(xiàn)一系列算法的實(shí)現(xiàn)上存在公共功能沟突,甚至這一系列算法的實(shí)現(xiàn)步驟都是一樣的,只是在某些局部步驟上有所不同捕传,這個(gè)時(shí)候惠拭,就需要對(duì)策略模式進(jìn)行些許的變化使用了。
對(duì)于一系列算法的實(shí)現(xiàn)上存在公共功能的情況庸论,策略模式可以有如下三種
實(shí)現(xiàn)方式:
- 1)在上下文當(dāng)中實(shí)現(xiàn)公共功能职辅,讓所有具體的策略算法回調(diào)這些方法。
- 2)把策略的接口改成抽象類聂示,然后在里面實(shí)現(xiàn)具體算法的公共功能域携。
- 3)給所有的策略算法定義一個(gè)抽象的父類,讓這個(gè)父類去實(shí)現(xiàn)策略的接口鱼喉,然后在這個(gè)父類里面去實(shí)現(xiàn)公共的功能秀鞭。
更進(jìn)一步,如果這個(gè)時(shí)候發(fā)現(xiàn)“一系列算法的實(shí)現(xiàn)步驟都是一樣的扛禽,只是在某些局部步驟上有所不同”的情況锋边,那就可以在這個(gè)抽象類里面定義算法實(shí)現(xiàn)的骨架,然后讓具體的策略算法去實(shí)現(xiàn)變化的部分编曼。這樣的一個(gè)結(jié)構(gòu)自然就變成了策略模式來結(jié)合模板方法模式了豆巨,那個(gè)抽象類就成了模板方法模式的模板類。
在前面我們討論過模板方法模式來結(jié)合策略模式的方式掐场,也就是主要的結(jié)構(gòu)是模板方法模式搀矫,局部采用策略模式。而這里討論的是策略模式來結(jié)合模板方法模式刻肄,也就是主要的結(jié)構(gòu)是策略模式瓤球,局部實(shí)現(xiàn)上采用模板方法模式。通過這個(gè)示例也可以看出來敏弃,模式之間的結(jié)合是沒有定勢(shì)的卦羡,要具體問題具體分析。
此時(shí)策略模式結(jié)合模板方法模式的系統(tǒng)結(jié)構(gòu)如下圖
3.7 策略模式的優(yōu)缺點(diǎn)
- 定義一系列算法
- 避免多重條件語句
- 更好的擴(kuò)展性
- 客戶必須了解每種策略的不同
- 增加了對(duì)象數(shù)目
- 只適合扁平的算法結(jié)構(gòu)
4.思考策略模式
4.1 策略模式的本質(zhì)
分離算法麦到,選擇實(shí)現(xiàn)
4.2 對(duì)設(shè)計(jì)原則的體現(xiàn)
策略模式很好的體現(xiàn)了開-閉原則绿饵。
策略模式通過把一系列可變的算法進(jìn)行封裝,并定義出合理的使用結(jié)構(gòu)瓶颠,使得在系統(tǒng)出現(xiàn)新算法的時(shí)候拟赊,能很容易的把新的算法加入到已有的系統(tǒng)中,而已有的實(shí)現(xiàn)不需要做任何修改粹淋。這在前面的示例中已經(jīng)體現(xiàn)出來了侄刽,好好體會(huì)一下。
從設(shè)計(jì)原則上來看将谊,策略模式還很好的體現(xiàn)了里氏替換原則。策略模式是一個(gè)扁平結(jié)構(gòu)葛碧,一系列的實(shí)現(xiàn)算法其實(shí)是兄弟關(guān)系,都是實(shí)現(xiàn)同一個(gè)接口或者繼承的同一個(gè)父類过吻。這樣只要使用策略的客戶保持面向抽象類型編程进泼,就能夠使用不同的策略的具體實(shí)現(xiàn)對(duì)象來配置它,從而實(shí)現(xiàn)一系列算法可以相互替換纤虽。
4.3 何時(shí)選用
- 1)出現(xiàn)有許多相關(guān)的類乳绕,僅僅是行為有差別的情況,可以使用策略模式來使用多個(gè)行為中的一個(gè)來配置一個(gè)類的方法逼纸,實(shí)現(xiàn)算法動(dòng)態(tài)切換
- 2)出現(xiàn)同一個(gè)算法洋措,有很多不同的實(shí)現(xiàn)的情況,可以使用策略模式來把這些“不同的實(shí)現(xiàn)”實(shí)現(xiàn)成為一個(gè)算法的類層次
- 3)需要封裝算法中樊展,與算法相關(guān)的數(shù)據(jù)的情況,可以使用策略模式來避免暴露這些跟算法相關(guān)的數(shù)據(jù)結(jié)構(gòu)
- 4)出現(xiàn)抽象一個(gè)定義了很多行為的類堆生,并且是通過多個(gè)if-else語句來選擇這些行為的情況专缠,可以使用策略模式來代替這些條件語句
5.案例
5.1 主題
開發(fā)一個(gè)客戶端框架,允許其他的開發(fā)者進(jìn)行二次開發(fā)淑仆,其中有一個(gè)更換主題的功能涝婉,開發(fā)者們可以自己定義主題。并且提供了一個(gè)默認(rèn)主題 DefaultTheme蔗怠。
public interface Theme {
public void showTheme();
}
public class DefaultTheme implements Theme {
@Override
public void showTheme() {
//此處設(shè)置主題顏色墩弯,背景,字體等
System.out.println("顯示默認(rèn)主題");
}
}
public class ThemeManager {
private Theme theme;
public void setTheme(Theme theme){
this.theme = theme;
}
public void showTheme(){
this.theme.showTheme();
}
}
使用:
ThemeManager themeManager = new ThemeManager();
themeManager.setTheme(new DefaultTheme());
themeManager.showTheme();
5.1.1 進(jìn)一步的修改——對(duì)修改封閉
themeManager.setTheme(new DefaultTheme());
如果其他開發(fā)者加了主題寞射,還要修改這行代碼渔工,new 開發(fā)者自定義的主題對(duì)象。根據(jù)開閉原則桥温,我們不希望其他人修改我們的任何一行代碼引矩。
將主題的包名和類名寫到了配置文件中,利用 Java 的反射機(jī)制動(dòng)態(tài)生成主題對(duì)象侵浸,因此更換主題也只要修改配置文件即可旺韭。
5.2 shiro
shiro 是 Java 界最著名的權(quán)限控制框架之一。在 shiro 中掏觉,可以創(chuàng)建多個(gè)權(quán)限驗(yàn)證器進(jìn)行權(quán)限驗(yàn)證区端,如驗(yàn)證器 A、驗(yàn)證器 B澳腹、驗(yàn)證器 C织盼,三個(gè)驗(yàn)證器可以同時(shí)生效杨何。
那么就產(chǎn)生了一個(gè)問題,如果驗(yàn)證器 A 驗(yàn)證通過悔政,B 驗(yàn)證不通過晚吞,C 驗(yàn)證通過,這種情況怎么辦谋国?到底算當(dāng)前用戶驗(yàn)證通過還是不通過呢槽地?
shiro 默認(rèn)提供了三種驗(yàn)證策略,就像默認(rèn)提供了一種主題一樣:
- AtLeastOneSuccessfulStrategy:只要有一個(gè)驗(yàn)證通過芦瘾,那么最終驗(yàn)證結(jié)果就是通過捌蚊。
- FirstSuccessfulStrategy:只有第一個(gè)成功地驗(yàn)證的 Realm 返回的信息將被使用,所有進(jìn)一步的 Realm 將被忽略近弟,如果沒有一個(gè)驗(yàn)證成功缅糟,則整體嘗試失敗。
- AllSucessfulStrategy:所有驗(yàn)證器都必須驗(yàn)證成功祷愉。
作為開發(fā)者窗宦,在使用 shiro 的時(shí)候,shiro 默認(rèn)的策略未必符合我們的需求二鳄,比如要求三個(gè)驗(yàn)證器中通過兩個(gè)才算通過赴涵,怎么辦?
很簡單订讼,shiro 這里用的也是策略模式髓窜,只要自定義一個(gè) MyAuthenticationStrategy 繼承 shiro 的 AbstractAuthenticationStrategy。前面不是說實(shí)現(xiàn)接口嗎欺殿,這里怎么是繼承寄纵?變通,要懂得變通脖苏。設(shè)計(jì)模式不是一成不變的程拭,重要的是這種編程思想。
然后在 MyAuthenticationStrategy 實(shí)現(xiàn)父類要求的方法棍潘,再修改配置文件將當(dāng)前驗(yàn)證策略改為你定義的驗(yàn)證策略:
authcStrategy = 你的包名.MyAuthenticationStrategy