从王者荣耀看设计模式(状态模式)
一.简介
英雄项羽在敌方英雄的攻击下存在3种不同的状态。
1.在健康生命值下——普通状态,在每次被攻击时,当前生命值=剩余生命值-敌方英雄伤害值
2.在生命值低于某一特定的值——被动状态,在每次被攻击时,当前生命值=剩余生命值-敌方英雄伤害值/2
3.英雄项羽生命值低于0——死亡状态
二.状态模式
状态模式:又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式,状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样
模式动机
在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的对象。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,使得系统的行为也随之改变。
在本实例中,英雄项羽类有三种状态,系统会根据计算英雄的生命值转换相应的状态。
- 这其中的设计原则有:
- 状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。
- 状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变
- 状态模式所涉及到的角色有:
环境(Context)角色,也成上下文:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。
- 状态模式的优点:
- 面向接口式编程,将实现细节巧妙封装在各个不同的状态类中,状态转换交给状态类自己去实现,外部无需关心;
- 将由大量业务、大量逻辑判断的代码去除,状态类内部通过状态的转换实现相关逻辑,代码可读性更好;
- 组合模式模式的缺点
- 增加新的状态时会增加状态类,而且在增加新的状态类之后,环境类需要做相应的修改,不太符合开闭原则
三.结构图
四.设计类图
五.代码实现
LifeState类(抽象状态类)
package com.game.LifeState;
import com.game.LifeManager.LifeManager;
/*
* 英雄项羽的游戏状态接口
* @param life 当前生命值
* @param lifeManager 状态上下文,用来在实现状态对应的功能处理的时候,可以回调上下文的数据
*/
public interface LifeState {
//英雄项羽被攻击的状态
public abstract void beAttacted(int life, LifeManager lifeManager);
}
NormalBeAttackedState类(具体状态类)——正常生命值状态
package com.game.LifeState.impl;
import com.game.LifeManager.LifeManager;
import com.game.LifeState.LifeState;
/*
* 英雄项羽在健康生命值下被攻击的状态
*/
public class NormalBeAttackedState implements LifeState {
public void beAttacted(int life, LifeManager lifeManager) {
//当前生命值=之前生命值-敌方英雄的攻击力
int newLife=lifeManager.getLife()-lifeManager.getHeroHurt();
System.out.print("英雄项羽正受到"+lifeManager.heroHurt+"点伤害,");
System.out.println("当前生命值为"+newLife);
//设置当前生命值
lifeManager.setLife(newLife);
}
}
AttactedUnderPassiveState类(具体状态类)——被动状态下
package com.game.LifeState.impl;
import com.game.LifeManager.LifeManager;
import com.game.LifeState.LifeState;
/*
* 当项羽生命值小于500,激发被动状态,所受伤害减半
*/
public class AttactedUnderPassiveState implements LifeState {
public void beAttacted(int life, LifeManager lifeManager) {
//设置在被动下项羽所受伤害值
int newHeroHurt=lifeManager.getHeroHurt()/2;
//设置被动状态下遭受攻击后当前血量
int newLife=lifeManager.getLife()-newHeroHurt;
//判断:在被动状态下如果生命值低于0,英雄死亡
if(newLife>0) {
System.out.println("英雄项羽激发被动陷阵之志,所受伤害减半");
System.out.print("英雄项羽正受到"+newHeroHurt+"点受害,");
System.out.println("当前的生命值为:"+newLife);
lifeManager.setLife(newLife);
}else {
System.out.println("英雄项羽已经死亡");
}
}
}
dieState类(具体状态类)——死亡状态
package com.game.LifeState.impl;
import com.game.LifeManager.LifeManager;
import com.game.LifeState.LifeState;
/*
* 英雄死亡状态
*/
public class dieState implements LifeState {
public void beAttacted(int life, LifeManager lifeManager) {
System.out.println("英雄项羽已经死亡");
}
}
LifeManager类(环境类)
package com.game.LifeManager;
import com.game.LifeState.LifeState;
import com.game.LifeState.impl.AttactedUnderPassiveState;
import com.game.LifeState.impl.NormalBeAttackedState;
import com.game.LifeState.impl.dieState;
/*
* 环境类
*/
public class LifeManager {
//持有状体处理对象
private LifeState state = null;
//项羽的初始生命值
private int life=1000;
//项羽收到敌方攻击的伤害值
public int heroHurt=0;
//构造方法初始化伤害值
public LifeManager(int heroHurt) {
this.heroHurt=heroHurt;
}
//get,set
public int getLife() {
return life;
}
public void setLife(int life) {
this.life = life;
}
public int getHeroHurt() {
return heroHurt;
}
public void setHeroHurt(int heroHurt) {
this.heroHurt = heroHurt;
}
public void beAttacked() {
if(life>500) {
state=new NormalBeAttackedState();
}else if(life>0 && life<=500) {
state=new AttactedUnderPassiveState();
}else if(life<=0) {
state=new dieState();
}
//转调状态对象执行相应操作
state.beAttacted(life, this);
}
}
LifeManagerTest类(测试类)
package com.game.test;
import com.game.LifeManager.LifeManager;
/*
* 测试类
*/
public class LifeManagerTest {
public static void main(String [] args) {
//设置项羽受到每次126的伤害
LifeManager lm=new LifeManager(126);
//设置项羽被相应伤害值攻击的次数
for(int i=0;i<15;i++) {
lm.beAttacked();
}
}
}