編輯:關於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鏈接以及鏈接成功,當然,這是只是模擬實現,實際上整個過程沒這麼簡單,比如需要先獲得卡號,然後異步鏈接,獲得返回的信息,鏈接是否成功等。
日志如下:
好了,到這裡,策略模式的介紹就完成了,稍後會把項目代碼上傳,希望對大家有幫助。
ListView是App開發中最常見的控件之一了,與之相隨的則是BaseAdapter的使用,BaseAdapter的作用則是為我們的ListView提供數據源,普通的用
用戶的聊天背景可以自定義,設置成自己喜歡的圖片,從而讓手機QQ更有個性,更具有個人特色。怎麼設置手機qq背景?手機qq設置聊天背景在哪?下面我們就一起來看看
(1)布局文件如下: 所需圖片:(2)MainActivity.javaimport android.app.Activity;import android.con
開發應用中圖片的使用是必不可少的,Android系統提供了豐富的圖片支持功能。我們除了可以使Drawable資源庫,還可以使用Bitmap、Picture類去創建圖片,也