1 Context The state pattern is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes.
2 Problem description In this example, a Hero can be in one of the 3 states: ALIVE, DEAD, INVISIBLE, SILENCED defined in HeroContext. When a Hero is ALIVE with hp0, it can attack, and can be attacked, silenced and disappear. When attacked, its hp is decreased by damage. If hp=0, a Hero enters the state of DEAD with hp=0. When silenced, a Hero enters the state of SILENCED. When disappear, a Hero enters the state of INVISIBLE. When a Hero is DEAD with hp=0, it can be revived. When revived, a Hero enters the state of ALIVE with full hp. When a Hero is SILENCED, it can be attacked, recovered and disappear. When attacked, its hp is decreased by damage. If hp¡=0, a Hero enters the state of DEAD with hp=0. When recovered, a Hero enters the state of ALIVE. When disappear, a Hero enters the state of INVISIBLE. When a Hero is INVISIBLE, it can appear.
public interface State {
void dealDamage(HeroContext target, double damage);
void takeDamage(HeroContext target, double damage);
void disappear(HeroContext target);
void appear(HeroContext target);
void revive(HeroContext target);
void silenced(HeroContext target);
void recover(HeroContext target);
}
public class Alive implements State {
@Override
public void dealDamage(HeroContext target, double damage) {
target.setHp(target.getHp() - damage);
if (target.getHp() <= 0) {
target.setState(new Dead());
}
}
@Override
public void takeDamage(HeroContext target, double damage) {
target.setHp(target.getHp() - damage);
if (target.getHp() <= 0) {
target.setState(new Dead());
}
}
@Override
public void disappear(HeroContext target) {
target.setState(new Invisible());
}
@Override
public void appear(HeroContext target) {
}
@Override
public void revive(HeroContext target) {
}
@Override
public void silenced(HeroContext target) {
target.setState(new Silenced());
}
@Override
public void recover(HeroContext target) {
}
}
public class Dead implements State {
@Override
public void dealDamage(HeroContext target, double damage) {
}
@Override
public void takeDamage(HeroContext target, double damage) {
}
@Override
public void disappear(HeroContext target) {
}
@Override
public void appear(HeroContext target) {
}
@Override
public void revive(HeroContext target) {
target.setHp(HeroContext.MAX_HP);
target.setState(new Alive());
}
@Override
public void silenced(HeroContext target) {
}
@Override
public void recover(HeroContext target) {
}
}
public class Invisible implements State {
@Override
public void dealDamage(HeroContext target, double damage) {
}
@Override
public void takeDamage(HeroContext target, double damage) {
}
@Override
public void disappear(HeroContext target) {
}
@Override
public void appear(HeroContext target) {
target.setState(new Alive());
}
@Override
public void revive(HeroContext target) {
}
@Override
public void silenced(HeroContext target) {
}
@Override
public void recover(HeroContext target) {
}
}
public class Silenced implements State {
@Override
public void dealDamage(HeroContext target, double damage) {
}
@Override
public void takeDamage(HeroContext target, double damage) {
target.setHp(target.getHp() - damage);
if (target.getHp() <= 0) {
target.setState(new Dead());
}
}
@Override
public void disappear(HeroContext target) {
target.setState(new Invisible());
}
@Override
public void appear(HeroContext target) {
}
@Override
public void revive(HeroContext target) {
}
@Override
public void silenced(HeroContext target) {
}
@Override
public void recover(HeroContext target) {
target.setState(new Alive());
}
}
public class HeroContext {
public static final int MAX_HP = 100;
private State state;
private double hp;
public HeroContext() {
state = new Alive();
hp = MAX_HP;
}
public double getHp() {
return hp;
}
public void setHp(double hp) {
this.hp = hp;
}
public void setState(State state) {
this.state = state;
}
public void dealDamage(HeroContext target, double damage) {
action("dealDamage", target, damage);
}
public void takeDamage(double damage) {
action("takeDamage", this, damage);
}
public void action(String action) {
this.action(action, this, 0);
}
private void action(String action, HeroContext target, double damage) {
if (action.equalsIgnoreCase("dealDamage")) {
state.dealDamage(target, damage);
} else if (action.equalsIgnoreCase("takeDamage")) {
state.takeDamage(target, damage);
} else if (action.equalsIgnoreCase("disappear")) {
state.disappear(target);
} else if (action.equalsIgnoreCase("appear")) {
state.appear(target);
} else if (action.equalsIgnoreCase("revive")) {
state.revive(target);
} else if (action.equalsIgnoreCase("silenced")) {
state.silenced(target);
} else if (action.equalsIgnoreCase("recover")) {
state.recover(target);
}
}
}
Comments
Leave a comment