作者 夏至 歡迎轉(zhuǎn)載,也請(qǐng)保留這段申明
http://blog.csdn.net/u011418943/article/details/73702423
很多對(duì)設(shè)計(jì)模式不太熟悉的小伙伴看到這個(gè)模式的時(shí)候,一臉懵逼?有這個(gè)模式,我怎么沒聽過(guò),好像不怎么常用啊! 你根本不是老司機(jī) ?。?! 別急,別先脫褲子,聽我講完。
1、策略模式定義
首先先解釋下,什么叫策略模式? 通俗來(lái)講,我們希望找出應(yīng)用中可能需要變動(dòng)的地方,把它們獨(dú)立出來(lái),并封裝起來(lái),不要和那些不需要變化的代碼混在一起 ,使代碼更加有彈性和擴(kuò)展性。
何為變動(dòng),比如生活中,一件衣服的價(jià)格總是變動(dòng),比如打折優(yōu)惠什么,比如旅行的方式,你可以選擇坐車,徒步或者坐飛機(jī)等等;而再 Android 中,這種模式也是非常常見的,比如 listview 的 setadpter() ,比如只是簡(jiǎn)單處理文字,我們可以使用 arrayadapter,simpleadapter,而稍微復(fù)雜一點(diǎn)的,則是使用 baseadapter,但最終我們調(diào)用的都是 setadapter,傳進(jìn)來(lái)的 adapter 其實(shí)用的 策略模式 (Strategy).
當(dāng)然經(jīng)常用的動(dòng)畫插值器也是用的策略模式,這個(gè)就是上面說(shuō)到的變動(dòng)的地方;
2、實(shí)踐
上面說(shuō)了一些理論的,下面我們來(lái)實(shí)踐一下。有個(gè)需求,有一家商店,衣服促銷,但是打折方式有三種
- 買一件打 9.7 折
- 買滿 200 減 20
- 買兩件以上打 9 折
看到這個(gè)需求,你可能是會(huì)說(shuō),這也太簡(jiǎn)單了吧,是的,我們來(lái)看看傳統(tǒng)寫法是怎么做的,首先定義一個(gè) discount 的類,easy,如下:
public class DisCount {
public static final int USE_PRECENT = 0; //使用百分比
public static final int USE_MOMEY = 1; //到底一定價(jià)錢返回現(xiàn)金
public static final int USE_TWO_PRESENT = 2; //兩件打多少折
private int strategy;
private float percent;
private float price;
public DisCount(int strategy, float price,float percent) {
this.strategy = strategy;
this.percent = percent;
this.price = price;
}
public float getPrice(){
switch (this.strategy){
case USE_PRECENT:
price = price * percent;
break;
case USE_MOMEY:
price = price - 20;
break;
case USE_TWO_PRESENT:
price = (price + price) * percent;
break;
}
return price;
}
}
上面的代碼中,很簡(jiǎn)單,通過(guò)一個(gè) switch 來(lái)選擇 mode ,然后計(jì)算出價(jià)錢,這里只是簡(jiǎn)單演示,就用就簡(jiǎn)單的邏輯了。然后再新建一個(gè) cashactivity 類:
public class CashActivity extends AppCompatActivity {
private static final String TAG = "zsr";
private float price;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DisCount disCount = null;
disCount = new DisCount(DisCount.USE_PRECENT,120,0.97f);
float price = disCount.getPrice();
Log.d(TAG, "我只買了一件衣服: "+price);
disCount = new DisCount(DisCount.USE_MOMEY,240,0);
price = disCount.getPrice();
Log.d(TAG, "我買了兩件衣服: "+price);
disCount = new DisCount(DisCount.USE_TWO_PRESENT,240,0.9f);
price = disCount.getPrice();
Log.d(TAG, "我買了兩件衣服: "+price);
}
}
很簡(jiǎn)單,就不解釋了,打印如下:

很明顯,在低價(jià)格,肯定是兩件減20劃算,當(dāng)兩件很貴的時(shí)候,肯定是打折便宜,等等,我寫什么東西,明顯個(gè)鬼啊,你根本不是程序猿?。?!
3、使用策略模式
好吧,假如現(xiàn)在老板覺得這樣還不夠吸引客戶,加多兩個(gè)需求
- 三件及以上享受 8.8 折優(yōu)惠
- 買滿1000元以上,除了享受8.8折,還能免費(fèi)辦理至尊卡一張,并立減 100
好吧,可能真的入錯(cuò)行了,應(yīng)該當(dāng)銷售的。。。。。
這個(gè)時(shí)候,你肯定會(huì)不屑一顧,這很簡(jiǎn)單啊,加多兩個(gè) case ,把邏輯寫進(jìn)去就行了!然而,老司機(jī)的車不是那么容易搭的,假如以后每次修改一下規(guī)則,或添加多幾個(gè)優(yōu)惠什么的,也要這樣嗎?這種在小規(guī)模還好,如果需求很多,這樣弄沒被弄死真的算不錯(cuò)的了,而且這也違背了設(shè)計(jì)原則了,而且擴(kuò)展性和彈性都不好。
怎么辦? 按照上面的理解,我們應(yīng)該把這部分變化的代碼抽取出來(lái)。
根據(jù)設(shè)計(jì)原則第二條: 針對(duì)接口編程,而不是針對(duì)實(shí)現(xiàn)編程。
所以,設(shè)計(jì)一個(gè)打折的接口:
public interface IDisCount {
float getPrice(int originPrice); //接口的函數(shù)只要一個(gè)原始價(jià)錢即可
}
想一下 listview 的 setadapter ,那么我們是不是也可以設(shè)置一個(gè) setdiscount ,只要輸入打折類型,就可以知道價(jià)格了?當(dāng)然可以,設(shè)計(jì)一個(gè)契約類,代碼如下:
public class DisCountControl {
private IDisCount iDisCount;
//設(shè)置使用哪種打折方式
public void setDisCount(IDisCount iDisCount){
this.iDisCount = iDisCount;
}
//返回價(jià)格
public float getFinalPrice(int originCash){
return this.iDisCount.getPrice(originCash);
}
}
那么,接下來(lái)只要在子類中,實(shí)現(xiàn) discount 的getPrice 即可了,上面有三個(gè),這里就寫三個(gè)把,如下:
單件打折:
public class DisCountPercent implements IDisCount {
private float mPercent;
public DisCountPercent(float mPercent) {
this.mPercent = mPercent;
}
@Override
public float getPrice(int originPrice) {
return originPrice * this.mPercent;
}
}
兩件減現(xiàn)金
public class CashDisCount implements IDisCount {
private float salemomey; //需要減的價(jià)格
public CashDisCount(float salemomey) {
this.salemomey = salemomey;
}
@Override
public float getPrice(int originPrice) {
return originPrice - salemomey;
}
}
** 兩件打折 **
public class MoreThanTwoClothesDisCount implements IDisCount{
private float mPercent;
public MoreThanTwoClothesDisCount(float mPercent) {
this.mPercent = mPercent;
}
@Override
public float getPrice(int originPrice) {
return originPrice * this.mPercent;
}
}
好吧,類的命名 low b 了點(diǎn),這里也是簡(jiǎn)單實(shí)現(xiàn)了邏輯,然后主函數(shù)那里:
public class CashActivity extends AppCompatActivity {
private static final String TAG = "zsr";
private float price;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IDisCount disCount = null;
DisCountControl disCountControl = new DisCountControl();
//單價(jià)
disCount = new DisCountPercent(0.99f);
disCountControl.setDisCount(disCount);
Log.d(TAG, "我只買了一件衣服: "+disCountControl.getFinalPrice(120));
//買兩件減現(xiàn)金
disCount = new CashDisCount(20);
disCountControl.setDisCount(disCount);
Log.d(TAG, "我只買了至少兩件衣服: "+disCountControl.getFinalPrice(240));
// 買了兩件打折的
disCount = new MoreThanTwoClothesDisCount(0.9f);
disCountControl.setDisCount(disCount);
Log.d(TAG, "我只買了至少兩件衣服: "+disCountControl.getFinalPrice(240));
}
}
可以看到,我們就new 了一個(gè)方法,然后用 discountcontrol.setDisCount 的類型就實(shí)現(xiàn)了我們的功能;
相較于原始的方式,雖然多了幾個(gè)類,但是擴(kuò)展性和彈性都變得更好了,不過(guò)那也不叫多幾個(gè)類,這樣單獨(dú)出來(lái)維護(hù)起來(lái)反而更加容易一些;
學(xué)會(huì)設(shè)計(jì)模式,更加讓我們的代碼健壯性和擴(kuò)展性更好,當(dāng)然這里只是簡(jiǎn)單的拋出一個(gè)實(shí)例,更多理解,要需要在實(shí)戰(zhàn)項(xiàng)目中;
這個(gè)模式會(huì)堅(jiān)持寫下去的,盡量用簡(jiǎn)單的例子,就算是小白也能理解這些模式,喜歡的可以關(guān)注一波哦。