设计模式之状态模式

        之前讲到的命令模式是将具体操作分离出来,而这里的状态模式也是相同的思路,将每种状态分离出来,建立状态类。状态模式的描述有很多种,比如状态模式封装基于状态的行为,并将行为委托到当前状态;又比如还有状态模式定义了对象的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新等等。无论状态模式的描述怎么变化,都是讲述了将对象的多种状态独立开来,即一个类代表一种状态。

1.适用性与优缺点
1.适用性:
a.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
b.一个操作中含有庞大的多分支的条件语句,且这些分治依赖于该对象的状态,这个状态通常用一个或多个枚举常量表示,通常,有多个操作包含这一相同的条件结构。状态模式将每一个条件分支放入一个独立类中。

2.优点:
a.状态模式将与特定状态相关的行为局部化,并且将不同状态行为分离出来。
b.所有状态相关的代码都存在某个状态中,所以通过定义新的子类很容易地增加新的状态和转换。
c.状态模式通过各种状态转移,逻辑分布到state的子类之间,来减少相互间的依赖。

3.缺点:
系统中有较多的状态类。

2.示例讲解
        我们讲一个天气的例子,我们都知道天气有很多种状态,每种状态都有不同的现象。如果我们放一个类中,则会产生很多逻辑判断,那么这个类过于冗杂,一旦更改,工作量会比较大。所以,我们将状态分离出来,做到每个状态一个类的原则。首先,我们还是遵循针对接口编程,因此建立一个状态接口。
package statepattern;

public interface Weather {
	String getWeather();
}
        这里举的例子简单点,所以在状态接口中只有一个方法,如果功能比较复杂,可以添加多个方法。以下是对状态接口的实现,有下雨,天晴,下雪等状态:
package statepattern;

public class Rain implements Weather {

	
	@Override
	public String getWeather() {
		// TODO Auto-generated method stub
		return "下雨";

	}

}
package statepattern;

public class Sunshine implements Weather {


	@Override
	public String getWeather() {
		// TODO Auto-generated method stub
		return "出太阳啦";
	}

}
package statepattern;

public class Snow implements Weather {

	@Override
	public String getWeather() {
		// TODO Auto-generated method stub
		return "下雪啦";
	}

}
        以上是每种状态对状态接口的实现,即实现了一个类代表一种天气状态,接下来这个类,则是为了对当前状态的操作,负责实例化具体状态,并且调用相应方法,表示当前状态的现象。

package statepattern;

public class Context {

    private Weather weather;

    public void setWeather(Weather weather) {
        this.weather = weather;
    }

    public Weather getWeather() {
        return this.weather;
    }

    public String weatherMessage() {
        return weather.getWeather();
    }
}
        以上Context类是一个简单的JavaBean,在运行时创建对象,体现了动态性,如果当前状态改变了,只需要通过Context类的setter函数进行状态动态地更换即可,并且可直接调用相应状态的函数。这样相当于减少了各个状态之间的依赖关系。接下来对示例进行测试:
package statepattern;

public class Test{

    public static void main(String[] args) {
        Context ctx1 = new Context();
        ctx1.setWeather(new Sunshine());
        System.out.println(ctx1.weatherMessage());

        System.out.println("===============");

        ctx1.setWeather(new Rain());
        System.out.println(ctx1.weatherMessage());
        
        System.out.println("===============");
        
        ctx1.setWeather(new Snow());
        System.out.println(ctx1.weatherMessage());
    }
}
        运行程序,结果如下:

出太阳啦
===============
下雨
===============
下雪啦
        由上面示例可以看出,通过各个具体的状态类以及Context类,实现了将具体类分离出来,减少了类转换的依赖关系。

3.与策略模式的对比
        其实状态模式与 策略模式十分相像,状态模式是将每种具体状态分离出来,而策略模式是将每种具体行为分离出来。两者还是有一些不同之处的。
1.状态模式是将一群行为封装在状态的对象中,Context的行为随时可委托到那些状态对象中的一个,当前状态在状态对象集合中游走改变,以反映出Context内部状态,内部决定了状态。而策略模式中对于Context来说,通常只有一个最合适的策略对象,相当于它是具体行为的组合而形成的策略对象。比如天气有好几种状态可以切换,而鸭子的行为方式、叫声是固定的,所以天气用状态模式可以表示多状态转换,而鸭子用策略模式表示行为和叫声只有一种最合适的策略模式。
2.一般策略模式是除继承之外的一种弹性替代方案,通过组合不同的对象来改变行为;而状态模式是将行为包装进状态对象中,可以通过在Context内简单地改变状态对象来改变Context的行为,替换了有许多条件判断的方案。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值