文字理解
分析下定義帆疟,策略模式定義和封裝了一系列的算法蚁吝,它們是可以相互替換的,也就是說它們具有共性垦缅,而它們的共性就體現(xiàn)在策略接口的行為上冲泥,另外為了達(dá)到最后一句話的目的,也就是說讓算法獨立于使用它的客戶而獨立變化壁涎,我們需要讓客戶端依賴于策略接口凡恍。
使用場景
1.針對同一類型問題的多種處理方式,僅僅是具體行為有差別時怔球;
2.需要安全地封裝多種同一類型的操作時嚼酝;
3.出現(xiàn)同一抽象類有多個子類,而又需要使用 if-else 或者 switch-case 來選擇具體子類時庞溜。
簡單描述
定義一個接口(例如計價接口)革半,多個類去實現(xiàn)這個接口(多種計價模式A,B流码,C)又官,最后再有一個類是實際計算的類Context,如果按照A計價模式計價漫试,只需new Context()時候六敬,調(diào)用ContextInterface()方法,ContextInterface()是根據(jù)傳入的策略對象來選擇其調(diào)用的接口方法的驾荣,從而實現(xiàn)策略選擇.
public class Context {
//持有一個具體策略的對象
private Strategy strategy;
/**
* 構(gòu)造函數(shù)外构,傳入一個具體策略對象
* @param strategy 具體策略對象
*/
public Context(Strategy strategy){
this.strategy = strategy;
}
/**
* 策略方法
*/
public void contextInterface(){
strategy.strategyInterface();
}
}
代碼理解
假設(shè)鵝廠推出了3種會員普泡,分別為會員,超級會員以及金牌會員审编,還有就是普通玩家撼班,針對不同類別的玩家,購買《王者農(nóng)藥》皮膚有不同的打折方式垒酬,并且一個顧客每消費(fèi)10000就增加一個級別砰嘁,那么我們就可以使用策略模式,因為策略模式描述的就是算法的不同勘究,這里我們舉例就采用最簡單的矮湘,以上四種玩家分別采用原價(普通玩家),九折口糕,八折和七價的收錢方式缅阳。
那么我們首先要有一個計算價格的策略接口
public interface CalPrice {
//根據(jù)原價返回一個最終的價格
Double calPrice(Double orgnicPrice);
}
下面是4種玩家的計算方式的實現(xiàn)
public class Orgnic implements CalPrice {
@Override
public Double calPrice(Double orgnicPrice) {
return orgnicPrice;
}
}
public class Vip implements CalPrice {
@Override
public Double calPrice(Double orgnicPrice) {
return orgnicPrice * 0.9;
}
}
public class SuperVip implements CalPrice {
@Override
public Double calPrice(Double orgnicPrice) {
return orgnicPrice * 0.8;
}
}
public class GoldVip implements CalPrice {
@Override
public Double calPrice(Double orgnicPrice) {
return orgnicPrice * 0.7;
}
}
我們看客戶類,我們需要客戶類幫我們完成玩家升級的功能景描。
public class Player {
private Double totalAmount = 0D;//客戶在鵝廠消費(fèi)的總額
private Double amount = 0D;//客戶單次消費(fèi)金額
private CalPrice calPrice = new Orgnic();//每個客戶都有一個計算價格的策略十办,初始都是普通計算,即原價
//客戶購買皮膚伏伯,就會增加它的總額
public void buy(Double amount) {
this.amount = amount;
totalAmount += amount;
if (totalAmount > 30000) {//30000則改為金牌會員計算方式
calPrice = new GoldVip();
} else if (totalAmount > 20000) {//類似
calPrice = new SuperVip();
} else if (totalAmount > 10000) {//類似
calPrice = new Vip();
}
}
//計算客戶最終要付的錢
public Double calLastAmount() {
return calPrice.calPrice(amount);
}
}
接下來是客戶端調(diào)用橘洞,系統(tǒng)會幫我們自動調(diào)整收費(fèi)策略捌袜。
public class Client {
public static void main(String[] args) {
Player player = new Player();
player.buy(5000D);
System.out.println("玩家需要付錢:" + player.calLastAmount());
player.buy(12000D);
System.out.println("玩家需要付錢:" + player.calLastAmount());
player.buy(12000D);
System.out.println("玩家需要付錢:" + player.calLastAmount());
player.buy(12000D);
System.out.println("玩家需要付錢:" + player.calLastAmount());
}
}
運(yùn)行以后會發(fā)現(xiàn)说搅,第一次是原價,第二次是九折虏等,第三次是八折弄唧,最后一次則是七價。這樣設(shè)計的好處是霍衫,客戶不再依賴于具體的收費(fèi)策略候引,依賴于抽象永遠(yuǎn)是正確的。
在上面的基礎(chǔ)上敦跌,我們可以使用簡單工廠來稍微進(jìn)行優(yōu)化
public class CalPriceFactory {
private CalPriceFactory(){}
//根據(jù)客戶的總金額產(chǎn)生相應(yīng)的策略
public static CalPrice createCalPrice(Player customer){
if (customer.getTotalAmount() > 30000) {//3000則改為金牌會員計算方式
return new GoldVip();
}else if (customer.getTotalAmount() > 20000) {//類似
return new SuperVip();
}else if (customer.getTotalAmount() > 10000) {//類似
return new Vip();
}else {
return new Orgnic();
}
}
}
這樣就將制定策略的功能從客戶類分離了出來澄干,我們的客戶類可以變成這樣。
public class Player {
private Double totalAmount = 0D;//客戶在鵝廠消費(fèi)的總額
private Double amount = 0D;//客戶單次消費(fèi)金額
private CalPrice calPrice = new Orgnic();//每個客戶都有一個計算價格的策略柠傍,初始都是普通計算麸俘,即原價
//客戶購買皮膚,就會增加它的總額
public void buy(Double amount) {
this.amount = amount;
totalAmount += amount;
/* 變化點惧笛,我們將策略的制定轉(zhuǎn)移給了策略工廠从媚,將這部分責(zé)任分離出去 */
calPrice = CalPriceFactory.createCalPrice(this);
}
//計算客戶最終要付的錢
public Double calLastAmount() {
return calPrice.calPrice(amount);
}
public Double getTotalAmount() {
return totalAmount;
}
}
雖然結(jié)合簡單工廠模式,我們的策略模式靈活了一些患整,但不免發(fā)現(xiàn)在工廠中多了if-else判斷拜效,也就是如果增加一個會員類別喷众,我又得增加一個else-if語句,這是簡單工廠的缺點紧憾,對修改開放到千。