策略模式适用场景:针对同一类型问题的多种处理方式,仅仅是具体行为有差别时。策略模式就是将每一个行为封装到具体的类,而且使他们可以自由选择和替换。
状态模式适用场景:状态模式和策略模式的结构差不多,但目的和本质不一样,状态模式的行为是平行的,不可替代的;而策略模式的行为是彼此独立,可相互替换的。状态模式的行为是由状态来决定的,不同的状态对应不同的行为。
代码实现:
策略模式:
需求:打车计费,有出租车,地铁,自行车3种选择,但是这3种方式是独立的,用户可以自由选择,只不过3种的收费标准不同。可以将他们的公有计费方法抽取出来:
Calculate.java
public interface Calculate{
int takePrice(int km);
}
Taxi.java
public class Taxi implements Calculate{
@Override
public int takePrice(int km) {
//具体实现,返回计算后的价格
return 0;
}
}
SubWay.java
public class SubWay implements Calculate{
@Override
public int takePrice(int km) {
//具体实现,返回计算后的价格
return 0;
}
}
Bike.java
public class Bike implements Calculate{
@Override
public int takePrice(int km) {
//具体实现,返回计算后的价格
return 0;
}
}
然后用的时候需要传递一个类似上下文的东西将这3个东西联系起来,根据用户选择来返回不同的实现。
Home.java
public class Home{
Calculate calculate;
public void setCalculate(Calculate calculate){
this.calculate = calculate;
}
public void calculatePrice(int km){
calculate.takePrice(km);
}
}
使用的时候直接
Home home = new Home();
home.setCalculate(new Bike());
home.calculatePrice(5);
home.setCalculate(new SubWay());
home.calculatePrice(5);
这样的好处是方便拓展,而且结构清晰,相比较传统的用if-else的做法优点明显。
从上面的例子可以看出,对于这些具体行为不同的同一类型问题,将这些不同的行为封装到具体的类,使用的时候只需要针对不同的选择来实例化不同的类,即可达到我们想要的目的。
状态模式:
需求:电视机有开机和关机两种状态,但是开机和关机时对于遥控器而要,他能响应的操作即行为是不同的,比如开机时按遥控器可以调台、关机等操作,但是关机时按遥控器除了开机键都不能响应。这里对应于状态模式的定义就是:当一个对象的状态改变时,允许改变其行为,并且不同的状态对应的行为相互平行,不可替代。
所以针对于上面的例子,可以先想一下,我们应该针对开机和关机两种状态,来决定不同的行为。所以说结构和策略模式相似,但是本质不一样。状态模式是根据状态不同来操作相互不可提交的行为,策略模式是根据状态不同去操作相互可替代的行为。
TvState.java//控制电视的行为
public interface TvState {
void powerOff();
void powerOn();
void nextChannel();
void previousChannel();
}
然后针对开机和关机2种状态来控制行为的具体实现:
PowerOffState .java//关机类
public class PowerOffState implements TvState {
@Override
public void powerOff() {
}
@Override
public void powerOn() {
//能响应开机,这里需要实现
}
@Override
public void nextChannel() {
}
@Override
public void previousChannel() {
}
}
PowerOnState .java //开机类
public class PowerOnState implements TvState {
@Override
public void powerOff() {
Log.e(TAG, “powerOff: “);
}
@Override
public void powerOn() {
//开机时再按开机是无响应的,无需实现
}
@Override
public void nextChannel() {
Log.e(TAG, "nextChannel: ");
}
@Override
public void previousChannel() {
Log.e(TAG, "previousChannel: ");
}
}
然后看context类:
public class TvControl {
TvState tvState;
public void setTvState(TvState tvState) {
this.tvState = tvState;
}
public void powerOn() {
setTvState(new PowerOnState());
}
public void powerOff() {
setTvState(new PowerOffState());
}
public void nextChannel(){
tvState.nextChannel();
}
public void previousChannel(){
tvState.previousChannel();
}
public void turnOn(){
tvState.powerOn();
}
public void turnOff(){
tvState.powerOff();
}
}
开机时:
TvControl control = new TvControl();
control.powerOn();
control.turnOn();
control.turnOff();
关机时:
TvControl control = new TvControl();
control.powerOff();
control.turnOn();
control.turnOff();
可以看出:状态模式和策略模式的结构相似,区别在于他们的行为是否独立,是否可替代。可以说这2中都是根据状态的不同去调用不同的实现,但是策略模式的行为本质和状态模式的行为本质不同,一个可替代,一个不可替代。