策略模式在android中使用

策略模式(Strategy)

策略模式是對象的行為模式。它的用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立類中,從而使得它們可以相互替換。策略模式使得算法可以在不修改或影響到調用端的情況下發生變化。

下面來討論下策略模式的結構類圖,具體如下:

從上面的結構圖中,我們可以看出策略模式涉及到瞭三個角色,具體角色如下所示:

A、抽象策略角色:這是個抽象角色,通常是由一個接口或是抽象類來實現。它為所有的具體策略類提供瞭需要的接口。

B、具體策略角色:這個角色包裝瞭相關的算法和行為,用來執行對應的策略事件。

C、環境角色:這個角色中含有一個對抽象策略類的引用,也是供外部調用直接接觸的角色。

下面具體舉個例子來使用策略模式。例子是這樣的:現在要做一個上網使用得app,接入的網絡類型有三種,分別為CMCC、ChinaNet及普通的Wifi類型,所以針對這幾種類型的網絡,我們需要定義一個抽象的策略角色,然後再定義三個具體角色,每個具體的角色中實現具體的功能細節,最後,我們在前端放置三個按鈕,點擊對應的按鈕調用對應的具體角色邏輯(通過調用抽象角色)。下面為我的代碼邏輯實現以及部分說明文字:

抽象策略角色(WifiConnectStrategy):

/**

* 抽象策略角色

*/

public abstract class WifiConnectStrategy implements Callback{

private WifiConnectStrategyListener listener = null;

protected WifiState wifiState = null;

 

protected Handler handler = null;

protected static final long CONN_WIFI_TIME = 2000; // 連接wifi的時間(模擬)

 

public WifiConnectStrategy() {

handler = new Handler(WifiConnectStrategy.this);

}

 

public voidsetWifiConnectStrategyListener(WifiConnectStrategyListener listener) {

this.listener = listener;

}

 

/**

* 創建一個策略,根據wifitype

*/

public static WifiConnectStrategycreateWithWifiType(WifiType wifiType) {

WifiConnectStrategy result = null;

switch (wifiType) {

case CMCC:

result = new CMCCWifiConnectStrategy();

break;

case CHINANET:

result = new ChinaNetWifiConnectStrategy();

break;

case COMMON:

result = new CommonWifiConnectStrategy();

break;

default:

break;

}

return result;

}

 

public voidconfigWifiState(WifiState wifiState) {

this.wifiState = wifiState;

}

 

/**

* 連接到網絡的方法

*/

public abstract void executeConnectNetRun();

 

/**

* 模擬鏈接後返回的結果

*/

public abstract void connectResult();

 

// 模擬網絡鏈接延遲

protected void simulateConnect() {

this.handler.removeMessages(1);

this.handler.sendEmptyMessageDelayed(1,CONN_WIFI_TIME);

}

 

@Override

public booleanhandleMessage(Message msg) {

connectResult();

return true;

}

 

public WifiConnectStrategyListener getListener() {

return listener;

}

 

public voidsetListener(WifiConnectStrategyListener listener) {

this.listener = listener;

}

 

public void log(String log) {

Log.d(WifiConnectStrategy, log);

}

 

}

 

具體策略角色(CMCC):

/**

* 具體策略角色

*/

public class CMCCWifiConnectStrategy extends WifiConnectStrategy {

 

public CMCCWifiConnectStrategy() {

super();

}

 

@Override

public voidexecuteConnectNetRun() {

log(cmcc connect …);

 

// 鏈接網絡核心代碼(異步)

// TODO

 

// 模擬網絡鏈接延遲

simulateConnect();

}

 

@Override

public void connectResult(){

getListener().cmccConnResult(this.wifiState.getWifiLabel() +連接成功!);

}

}

 

具體策略角色(ChinaNet):

public classChinaNetWifiConnectStrategy extendsWifiConnectStrategy {

 

public ChinaNetWifiConnectStrategy() {

super();

}

 

@Override

public voidexecuteConnectNetRun() {

log(chinanet connect …);

 

// 鏈接網絡核心代碼

// TODO

 

// 模擬網絡鏈接延遲

simulateConnect();

}

 

@Override

public void connectResult(){

getListener().cmccConnResult(this.wifiState.getWifiLabel() +連接成功!);

}

}

 

具體策略角色(Common wifi):

public classCommonWifiConnectStrategy extendsWifiConnectStrategy {

 

public CommonWifiConnectStrategy() {

super();

}

 

@Override

public void executeConnectNetRun(){

log(common connect …);

 

// 鏈接網絡核心代碼

// TODO

 

// 模擬網絡鏈接延遲

simulateConnect();

}

 

@Override

public void connectResult(){

getListener().cmccConnResult(this.wifiState.getWifiLabel() +連接成功!);

}

 

}

 

下面為我們具體的環境角色,主要就是引用一個抽象策略角色,以及根據不同網絡類型創建對應的具體策略角色,具體如下:

public class MainActivity extends Activity implements OnClickListener {

private Button btnCmcc = null;

private Button btnChinanet = null;

private Button btnCommon = null;

 

private WifiConnectStrategy wifiConnectStrategy;

 

private WifiState selectedState = new WifiState();

 

private WifiConnectStrategyListener listener = new WifiConnectStrategyListener() {

@Override

public voidcmccConnResult(String state) {

log(state);

}

 

@Override

public void chinanetConnResult(Stringstate) {

log(state);

}

 

@Override

public voidcommonConnResult(String state) {

log(state);

}

 

};

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

 

btnCmcc = (Button) findViewById(R.id.btnCmcc);

btnChinanet = (Button) findViewById(R.id.btnChinanet);

btnCommon = (Button) findViewById(R.id.btnCommon);

 

btnCmcc.setOnClickListener(this);

btnChinanet.setOnClickListener(this);

btnCommon.setOnClickListener(this);

}

 

@Override

public void onClick(View v) {

if (null != wifiConnectStrategy) {

wifiConnectStrategy = null;

}

 

if(v.getId() == R.id.btnCmcc) {

selectedState.setCardNo(cmcc+1167278922);

selectedState.setIpAddress(192168013);

selectedState.setPassword(123456);

selectedState.setWifiLabel(CMCC);

selectedState.setSsid(dafadfdadada);

selectedState.setWifiType(WifiType.CMCC);

wifiConnSpecial(selectedState);

}

else if (v.getId() == R.id.btnChinanet) {

selectedState.setCardNo(cmcc+1167272222);

selectedState.setIpAddress(192168433);

selectedState.setPassword(123456777);

selectedState.setWifiLabel(ChinaNet);

selectedState.setSsid(dafadeeeedada);

selectedState.setWifiType(WifiType.CHINANET);

wifiConnSpecial(selectedState);

}

else {

selectedState.setIpAddress(192168111);

selectedState.setPassword(123456789);

selectedState.setWifiLabel(COMMON);

selectedState.setSsid(dafadeeeSSDASF);

selectedState.setWifiType(WifiType.COMMON);

wifiConnCommon(selectedState);

}

}

 

private voidwifiConnSpecial(WifiState wifiState) {

wifiConnectStrategy = WifiConnectStrategy.createWithWifiType(selectedState.getWifiType());

wifiConnectStrategy.configWifiState(wifiState);

wifiConnectStrategy.setWifiConnectStrategyListener(listener);

wifiConnectStrategy.executeConnectNetRun();

}

 

private voidwifiConnCommon(WifiState wifiState) {

wifiConnectStrategy = WifiConnectStrategy.createWithWifiType(selectedState.getWifiType());

wifiConnectStrategy.configWifiState(wifiState);

wifiConnectStrategy.setWifiConnectStrategyListener(listener);

wifiConnectStrategy.executeConnectNetRun();

}

 

private void log(String log) {

Log.d(WifiConnectStrategy,log);

}

}

 

註意:這裡的WifiState類為wifi的封裝類,WifiConnectStrategyListener為監聽網絡鏈接的接口。接下來,我會在下面羅列出他們的代碼構成。

WifiState:

public class WifiState {

// wifi name

private String wifiLabel;

// wifi ip

private int ipAddress;

// wifi ssid

private String ssid;

// wifi password

private String password;

// card no

private String cardNo;

// 類型

private WifiType wifiType;

 

// wifi 類型

public enum WifiType {

CMCC(1),

CHINANET(2),

COMMON(3);

 

private final int type;

 

private WifiType(int type) {

this.type = type;

}

 

public int getType() {

return type;

}

 

public static WifiTypegetType(int wifiType) {

WifiTypetype = null;

if(WifiType.CMCC.getType() == wifiType) {

type = WifiType.CMCC;

}

else if(WifiType.CHINANET.getType() == wifiType) {

type = WifiType.CHINANET;

}

else if(WifiType.COMMON.getType() == wifiType) {

type = WifiType.COMMON;

}

return type;

}

}

 

public int getIpAddress() {

return ipAddress;

}

 

public void setIpAddress(int ipAddress) {

this.ipAddress = ipAddress;

}

 

public String getSsid() {

return ssid;

}

 

public void setSsid(String ssid) {

this.ssid = ssid;

}

 

public String getPassword() {

return password;

}

 

public voidsetPassword(String password) {

this.password = password;

}

 

public String getCardNo() {

return cardNo;

}

 

public void setCardNo(StringcardNo) {

this.cardNo = cardNo;

}

 

public String getWifiLabel() {

return wifiLabel;

}

 

public voidsetWifiLabel(String wifiLabel) {

this.wifiLabel = wifiLabel;

}

 

public WifiType getWifiType() {

return wifiType;

}

 

public voidsetWifiType(WifiType wifiType) {

this.wifiType = wifiType;

}

}

 

WifiConnectStrategyListener:

/**

* wifi鏈接的監聽

*/

public interfaceWifiConnectStrategyListener {

 

public voidcmccConnResult(String state);

 

public voidchinanetConnResult(String state);

 

public voidcommonConnResult(String state);

 

}

 

好瞭,運行下代碼,頁面效果如下:

當我們點擊對應的按鈕鏈接網絡時,會在輸出日志打印對應的wifi鏈接以及鏈接成功,當然,這是隻是模擬實現,實際上整個過程沒這麼簡單,比如需要先獲得卡號,然後異步鏈接,獲得返回的信息,鏈接是否成功等。

日志如下:

 

 

好瞭,到這裡,策略模式的介紹就完成瞭,稍後會把項目代碼上傳,希望對大傢有幫助。

 

 

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。