设计模式2:state pattern
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
这句黑话,我头几次看,不能理解。但当踏踏实实敲一遍代码后,有了一点自己的理解:
举个例子,一个游戏角色有行走,跳,跑等几个状态,我们如何编码让游戏对象从一个状态到另一个状态时,行为也自动随之改变,而之后修改状态时,无需再来修改高层的类呢。设计模式里有一个原则,对接口编程,不对实现编程。如何联系对象和对象状态呢?我们用接口(抽象类,接口,父类,总之一句话,实现运行时多态即可)。
四人帮GOF的设计模式里有张图,非常简洁清晰的说明了问题。
其中Context就是游戏对象,游戏对象有一个State类型的游戏状态成员,request()方法调用State->handle实现功能即可。
测试代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeroineState {
public class Heroine{
public void HandleInput() { state.HandleInput(); }
public HeroineState NextState() { return state = state.NextState(); }
//public HeroineState State { get; set; }
private HeroineState state = StandingState.GetStand;
}
public class HeroineState {
//private static StandingState standing; // 如果类是抽象类就只是声明了,其子类实例化
//private static JumpingState jumping;
//private static StandingState standing = new StandingState(); // 子类父类共享的字段. 如果类包含静态字段,则提供在类加载时初始化它们的静态构造函数。或者声明时直接初始化
public virtual void HandleInput() { }
public virtual HeroineState NextState() { return null; }
}
public class StandingState:HeroineState{
private StandingState() { }
private static StandingState standing = new StandingState();
public static StandingState GetStand {
get {
return standing;
}
}
public float chargeTime = 0;
public override void HandleInput() {
if(Input.GetButton("Fire123"))
Debug.Log("Fire when standing!!");
}
public override HeroineState NextState() {
if (Input.GetButton("jump")) {
Debug.Log("stand to jump");
return JumpingState.GetJump;
}
else if (Input.GetButton("Stand")) {
Debug.Log("keep standing");
return this;
}
//Debug.Log("No if call");
return this;
}
}
public class JumpingState : HeroineState {
private JumpingState() { }
private static JumpingState jumping = new JumpingState();
public static JumpingState GetJump {
get {
return jumping;
}
}
public float chargeTime = 0;
public override void HandleInput() {
if (Input.GetButton("Fire123"))
Debug.Log("Fire when jumping!!");
}
public override HeroineState NextState() {
if (Input.GetButton("Stand")) {
Debug.Log("jump to stand");
return StandingState.GetStand;
}
else if(Input.GetButton("jump")){
Debug.Log("keep jumping!");
return this;
}
//Debug.Log("No if call");
return this;
}
}
}