1、定義:
The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from
clients that use it.
定義了一系列的算法(這些算法實現了相同的工作,只是實現不同),它可以已相同的方式調用所有的算法,減少算法類與算法之間的耦合。
2、目的:
將具體的算法抽象出來,把每個算法獨立出來,形成一系列的算法組,這個算法組裏面的算法可以根據實際情況進行相互替換。
3、中心:
策略模式的中心,不在於如何實現算法,而在於如何組織和調用這些算法,即:解耦合,形成獨立模塊,增強程序拓展性。
寫了一個簡單的策略使用
首先,編寫一個統一的算法接口
/**
* 策略模式
* 統一的算法接口
* @author qubian
* @data 2015年6月3日
* @email [email protected]
*
*/
public interface StrategyPattern {
/**
* 計算注數
*/
public int calcLottery(int num);
}
其次,編寫每個具體的實現
package com.example.demo;
/**
* 策略模式
* 具體的方法實現;
* 比如說雙色球
* @author qubian
* @data 2015年6月3日
* @email [email protected]
*
*/
public class StrategyPatternImp_SSQ implements StrategyPattern {
@Override
public int calcLottery(int num) {
return 0;
}
}
package com.example.demo;
/**
* 策略模式
* 具體的方法實現;
* 比如說大樂透
* @author qubian
* @data 2015年6月3日
* @email [email protected]
*
*/
public class StrategyPatternImp_DLT implements StrategyPattern{
@Override
public int calcLottery(int num) {
return 0;
}
}
最後是策略的不同調用
package com.example.demo;
/**
* 具體的使用
* @author qubian
* @data 2015年6月3日
* @email [email protected]
*
*/
public class LotteryCount {
private StrategyPattern strategyPattern;
public enum LotteryEnum {
SSQ, DLT, QLC;
}
public int getLotteryCount(LotteryEnum e,int num)
{
switch (e) {
case SSQ:
strategyPattern = new StrategyPatternImp_SSQ();
break;
case DLT:
strategyPattern = new StrategyPatternImp_DLT();
break;
default:
break;
}
return strategyPattern.calcLottery(num);
}
}
策略模式 在Android Framework 中運用廣泛;
比如說,我們經常使用的 BaseAdapter 實際也是策略模式;
我們編寫的適配器繼承自BaseAdapter,通過getview中實現不同的算法,實現不同的view的返回,
外部使用時也可以根據數據源,切換Adapter,這樣的使用其實就是一種策略模式;
Adapter 就是一個最頂層的策略接口
public interface Adapter {
/**
* How many items are in the data set represented by this Adapter.
*
* @return Count of items.
*/
int getCount();
/**
* Get the data item associated with the specified position in the data set.
*
* @param position Position of the item whose data we want within the adapter's
* data set.
* @return The data at the specified position.
*/
Object getItem(int position);
/**
* Get a View that displays the data at the specified position in the data set. You can either
* create a View manually or inflate it from an XML layout file. When the View is inflated, the
* parent View (GridView, ListView...) will apply default layout parameters unless you use
* {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}
* to specify a root view and to prevent attachment to the root.
*
* @param position The position of the item within the adapter's data set of the item whose view
* we want.
* @param convertView The old view to reuse, if possible. Note: You should check that this view
* is non-null and of an appropriate type before using. If it is not possible to convert
* this view to display the correct data, this method can create a new view.
* Heterogeneous lists can specify their number of view types, so that this View is
* always of the right type (see {@link #getViewTypeCount()} and
* {@link #getItemViewType(int)}).
* @param parent The parent that this view will eventually be attached to
* @return A View corresponding to the data at the specified position.
*/
View getView(int position, View convertView, ViewGroup parent);
static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE;
int getItemViewType(int position);
int getViewTypeCount();
static final int NO_SELECTION = Integer.MIN_VALUE;
boolean isEmpty();
}
再到BaseAdapter的抽象
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public boolean hasStableIds() {
return false;
}
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent);
}
public int getItemViewType(int position) {
return 0;
}
public int getViewTypeCount() {
return 1;
}
public boolean isEmpty() {
return getCount() == 0;
}
}