《Android源代碼設計模式解析與實戰》讀書筆記(八)
阿新 • • 發佈:2017-06-29
code androi nal clas 函數 轉發 類和對象 cti comment
第八章、狀態模式
1.定義
狀態模式中的行為是由狀態來決定,不同的狀態下有不同的行為。當一個對象的內在狀態改變時同意改變其行為,這個對象看起來像是改變了其類。
2.使用場景
1.一個對象的行為取決於它的狀態,而且它必須在執行時依據狀態改變它的行為。
2.代碼中包括大量與對象狀態有關的條件語句,比如,一個操作中含有大量的多分支語句。且這些分支依賴於該對象的狀態。
3.簡單實現
實現效果:首先將電視的狀態分為開機與關機狀態,開機時能夠通過遙控器實現頻道切換和調節音量,可是關機時,這些操作都會失效。
首先是普通的實現方法:
public class TVController {
//開機狀態
private final static int POWER_ON = 1;
//關機狀態
private final static int POWER_OFF = 2;
//默認狀態
private int mState = POWER_OFF;
public void powerOn(){
if(mState ==POWER_OFF){
System.out.println("電視開機了");
}
mState = POWER_ON;
}
public void powerOff(){
if(mState ==POWER_ON){
System.out.println("電視關機了");
}
mState = POWER_OFF;
}
public void nextChannel(){
if(mState ==POWER_ON){
System.out.println("下一頻道");
}else{
System.out.println("沒有開機");
}
}
public void prevChannel(){
if(mState ==POWER_ON){
System.out.println("上一頻道");
}else{
System.out.println("沒有開機");
}
}
public void turnUp(){
if(mState ==POWER_ON){
System.out.println("調高音量");
}else{
System.out.println("沒有開機");
}
}
public void turnDown(){
if(mState ==POWER_ON){
System.out.println("調低音量");
}else{
System.out.println("沒有開機");
}
}
}
能夠看到,每次執行通過推斷當前狀態來進行操作。部分的代碼反復。如果狀態和功能添加,就會越來越難以維護。這時能夠使用狀態模式。例如以下:
電視的操作
/**
* 電視狀態接口,定義了電視的操作函數
*
* */
public interface TVState {
public void nextChannel();
public void prevChannel();
public void turnUp();
public void turnDown();
}
關機狀態
/**
*
* 關機狀態,操作無結果
*
* */
public class PowerOffState implements TVState{
@Override
public void nextChannel() {
}
@Override
public void prevChannel() {
}
@Override
public void turnUp() {
}
@Override
public void turnDown() {
}
}
開機狀態
/**
*
* 開機狀態。操作有效
*
* */
public class PowerOnState implements TVState{
@Override
public void nextChannel() {
System.out.println("下一頻道");
}
@Override
public void prevChannel() {
System.out.println("上一頻道");
}
@Override
public void turnUp() {
System.out.println("調高音量");
}
@Override
public void turnDown() {
System.out.println("調低音量");
}
}
電源操作接口
/**
* 電源操作接口
*
* */
public interface PowerController {
public void powerOn();
public void powerOff();
}
電視遙控器
/**
* 電視遙控器
*
* */
public class TVController implements PowerController{
TVState mTVState;
public void setTVState(TVState mTVState){
this.mTVState = mTVState;
}
@Override
public void powerOn() {
setTVState(new PowerOnState());
System.out.println("開機了");
}
@Override
public void powerOff() {
setTVState(new PowerOffState());
System.out.println("關機了");
}
public void nextChannel(){
mTVState.nextChannel();
}
public void prevChannel(){
mTVState.prevChannel();
}
public void turnUp(){
mTVState.turnUp();
}
public void turnDown(){
mTVState.turnDown();
}
}
調用:
public class Client {
public static void main(String[] args) {
TVController tvController = new TVController();
//設置開機狀態
tvController.powerOn();
//下一頻道
tvController.nextChannel();
//調高音量
tvController.turnUp();
//關機
tvController.powerOff();
//調低音量,此時不會生效
tvController.turnDown();
}
}
結果
開機了
下一頻道
調高音量
關機了
能夠看出。狀態模式將這些行為封裝到狀態類中。在進行操作時將這些功能轉發給狀態對象,不同的狀態有不同的實現,去除了反復了if-else語句,這正是狀態模式的精髓所在。
4.與策略模式的差別
狀態模式與策略模式的結構差點兒是一樣的,就像是孿生兄弟。可是他們的目地、本質不一樣。
狀態模式的行為是平行的、不可替換的。策略模式的行為是彼此獨立的、可相互替換的。狀態模式,一般是自我控制狀態的改變。而策略模式,是由外部指定使用什麽樣的策略。
5.Android實戰中的使用
1.登錄系統,依據用戶是否登錄。推斷事件的處理方式。
2.Wi-Fi管理,在不同的狀態下,WiFi的掃描請求處理不一。
6.總結
1.長處
將全部與一個特定的狀態相關的行為都放入一個狀態對象中,它提供了一個更好的方法來組織與特定狀態相關的代碼。將繁瑣的狀態推斷轉換成結構清晰的狀態類族。在避免代碼膨脹的同一時候也保證了可擴展性與可維護性。
2.缺點
狀態模式的使用必定會添加系統類和對象的個數。
《Android源代碼設計模式解析與實戰》讀書筆記(八)