越來越多的應用登錄操作不是進入的必須條件了。
很多都是在一些必要的操作的時候纔會判斷登錄,例如評論,轉發,支付等功能。
大部分童鞋應該都是在點擊對應按鈕的時候去判斷登錄的狀態吧:
if(已登錄){
}else {
}
這樣不好,其實大家都知道不好,每加一個按鈕或者需要這樣的入口你就需要寫一次上面的代碼。
如果又加了第三個狀態判斷你就要在每一個上面代碼的地方再加一個else if。
那應該怎麼辦呢?
下面介紹一下狀態模式:
狀態模式中的行爲是由狀態來決定的,不同狀態下有不同的行爲。
它的意圖是讓一個對象在其內部狀態改變的時候,其行爲也隨之改變。
狀態模式使用場景:
1.一個對象的行爲取決於她的狀態,並且她的必須在運行時根據狀態改變她的行爲。
2.代碼中包含大量與對象狀態有關的條件語句,例如,一個操作中含有龐大的多分枝語句(if else或switch-case),並且這些分支依賴於該對象的狀態。
狀態模式將每一個條件分支放入一個獨立的類中,這使得你可以根據對象自身的情況將對象的狀態作爲一個對象,這一對象可以不依賴於其他對象而獨立變化,這樣通過多態來去除過多的,重複的if-else。
說了這麼多太抽象,下面貼出一段簡單的代碼。
代碼場景:有三個按鈕,分別是購買 發表評論 退出登錄。默認是未登錄狀態,點擊了購買或者發表評論按鈕時候會將操作動作發送給用戶狀態管理類來處理。
這樣好處就是,當突然加了某一個判斷條件,或者加了一個需要判斷的入口的時候,可以統一的去處理。
狀態模式使用場景還是比較廣泛的,多用幾次就能熟練了。
下面的例子是《Android 設計模式 解析與實戰》第八章 狀態模式中整理出來的。
首先將用戶動作抽象出來:
/**
* 用戶狀態
* Created by ge on 2017/5/2.
*/
public interface UserState {
// 購買
void payment(Context context);
// 發表評論
void comment(Context context);
}
然後是已登錄狀態的操作類,如下:
已登錄狀態下就進行具體對應的操作即可
/**
* 登錄狀態下
* Created by ge on 2017/5/2.
*/
public class LoginState implements UserState {
@Override
public void payment(Context context) {
Toast.makeText(context, "購買成功", Toast.LENGTH_SHORT).show();
}
@Override
public void comment(Context context) {
Toast.makeText(context, "評論成功", Toast.LENGTH_SHORT).show();
}
}
對應已登錄狀態的就是未登錄狀態的操作類:
未登錄狀態下就跳轉到登錄界面。
/**
* 爲登錄狀態
* Created by ge on 2017/5/2.
*/
public class LogoutState implements UserState{
@Override
public void payment(Context context) {
goLogin(context);
}
@Override
public void comment(Context context) {
goLogin(context);
}
/**
* 跳轉登錄頁
*/
private void goLogin(Context context) {
context.startActivity(new Intent(context, LoginActivity.class));
}
}
然後就是用戶狀態統一管理類了:
將判斷用戶是否登錄發送給下面的logincontext類來處理。
/**
* 用戶狀態管理類
* Created by ge on 2017/5/2.
*/
public class LoginContext {
// 默認未登錄狀態
UserState userState = new LogoutState();
// 單例
private static LoginContext loginContext = new LoginContext();
private LoginContext(){
}
public static LoginContext getLoginContext() {
return loginContext;
}
public void setUserState(UserState userState){
this.userState = userState;
}
// 購買
public void payment(Context context){
userState.payment(context);
}
// 發表評論
public void comment(Context context){
userState.comment(context);
}
}
登錄界面:
只有一個按鈕,點擊登錄按鈕設置用戶的狀態。
/**
* 登錄頁面
* Created by ge on 2017/5/2.
*/
public class LoginActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// 登錄
findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 設置已登錄狀態
LoginContext.getLoginContext().setUserState(new LoginState());
LoginActivity.this.finish();
}
});
}
}
最後看一下那三個按鈕的界面:
點擊對應按鈕,將處理交給用戶狀態統一的操作類。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 購買
findViewById(R.id.btn_payment).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LoginContext.getLoginContext().payment(MainActivity.this);
}
});
// 發表評論
findViewById(R.id.btn_comment).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LoginContext.getLoginContext().comment(MainActivity.this);
}
});
// 退出登錄
findViewById(R.id.btn_logout).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 設置退出登錄狀態
LoginContext.getLoginContext().setUserState(new LogoutState());
Toast.makeText(MainActivity.this, "已退出登錄", Toast.LENGTH_SHORT).show();
}
});
}
}