Android 设计模式--状态模式

1.状态模式

状态模式State Pattern,是行为型设计模式。

状态模式指的是当一个对象的内在状态改变时,其行为也随之改变。即状态模式中的行为是由状态决定的,不同的状态下有不同的行为。

状态模式把对象的行为包装在不同的状态对象里,每一个状态对象都有一个共同的抽象状态基类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。

状态模式和策略模式的机构几乎完全一样,但它们的目的、本质却完全不一样。状态模式的行为是平行的,不可替换的,但策略模式的行为是彼此独立、可相互替换的。

UML类图:

72b592b7dd5741d382f48296c444e91c.webp

①Context:环境类,定义用户感兴趣的接口,维护一个State子类的实例,这个实例定义了对象的当前状态。

②State:抽象状态类或者状态接口,定义一个或者一组接口,表示该状态下的行为。也就是在这里定义各种行为方法

③ConcreteStateA,ConcreteStateB:具体状态类,每一个具体的状态类实现抽象状态类中定义的接口,从而达到不同状态下的不同行为。具体状态类主要有两个职责,一是处理本状态下的事情,二是从本状态如何过渡到其他状态。

 

适用场景:

一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。

一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。

 

优点:

①将繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了可扩展性和可维护性。

②体现了开闭原则和单一职责原则,每个状态都是一个子类,要增加状态只需增加子类,要修改状态只需修改一个子类即可。

③符合迪米特法则。

缺点:会增加系统类和对象的个数。

 

2.举例

比如一个app,它的状态有已登录和未登录两种。点击转发和评论按钮时,如果是已登录状态则可以跳转到转发、评论页面,如果是未登录状态则跳转登录界面。也就是说app的内部状态决定了转发和评论按钮的行为。

①定义状态接口,里面是按钮的各种操作行为

public interface UserState {

    public void forward(Context context);//转发

    public void comment(Context context);//评论

}

②具体的实现类--已登陆状态

public class LoginState implements UserState {

    @Override

    public void forward(Context context) {

      Toast.makeText(context, "跳转到转发页", Toast.LENGTH_LONG).show();

    }

    @Override

    public void comment(Context context) {

        Toast.makeText(context, "跳转评论页", Toast.LENGTH_LONG).show();

    }

}

③具体的实现类--未登陆状态

public class logoutState implements UserState {

    @Override

    public void forward(Context context) {

        gotoLoginActivity(context);

    }

    @Override

    public void comment(Context context) {

        gotoLoginActivity(context);

    }

    private void gotoLoginActivity(Context context) {

        Intent intent = new Intent(context, LoginActivity.class);

        context.startActivity(intent);

    }

}

④定义控制类接口

public interface ILoginContext {

    public void loginState();

    public void logoutState();

}

⑤实现控制类

public class LoginContext implements ILoginContext{

    UserState userState = new logoutState();//用户状态,认为未登录状态

    public void setUserState(UserState userState){

        this.userState = userState;

     }

    @override

    public void loginState(){

        setUserState(new LoginState());

    }

    public void logoutState(){

        setUserState(new logoutState());

    }

    public void forward(Context context) {

        userState.forward(context);

    }

    public void comment(Context context) {

        userState.comment(context);

    }    

}

⑥客户端调用

LoginContext loginContext = new LoginContext();

loginContext.loginState();//设置为已登录状态

loginContext.forward();//跳到转发页面

loginContext.comment();//跳到评论页面

loginContext.logoutState();//设置为未登录状态

loginContext.forward();//跳到登录页面

loginContext.comment();//跳到登录页面

首先抽象了一个UserState接口,该接口中有用户可操作的所有行为。它有两个实现类,即已登录状态和未登录状态,已登录状态下点击转发和评论按钮可跳转到对应页面,关机状态下都跳到登录页面。app的内部状态影响了按钮的跳转行为。状态模式将这些行为封装到状态类中,在进行操作时将这些功能转发给状态对象,不同的状态有不同的实现,这样就通过多态的形式去除了重复的if-else语句,这也正是状态模式的精髓所在。

 

3.总结

状态模式的关键点在于不同的状态下对于同一行为有不同的响应,这其实就是一个将if-else用多态来实现的一个具体实例。在if-else或者switc-case形势下根据不同的状态进行判断,如果是A那么执行方法A,状态B执行方法B,但这种实现使得逻辑耦合在一起,易于出错,通过状态模式能够很好地消除这类“丑陋”的逻辑处理。

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...
win11本地账户怎么改名?win11很多操作都变了样,用户如果想要...