一个对象的行为其属性的动态变化,这样的属性叫状态,这类对象也叫做有状态的对象。当此类对象被某一事件修改其内部状态时,程序的行为也要随之改变
状态模式又称状态对象模式(Pattern of Objects for States)是用于解决对象的复杂状态及不同状态下的行为的一种模式。
模式定义
状态模式允许一个对象在其内部属性改变的时候改变其行为,这个对象看上去就像是改变了它的类一样
模式结构
状态模式涉及角色:
- 环境角色(Context):定义客户感兴趣的接口,并保留一个具体状态类的实例
- 抽象状态角色(State):定义一个借口,封装特定状态下的对应行为
- 具体状态角色(ConcreteState):抽象状态角色的子类,每个子类实现了相关的行为
Tip:
- 该图为UML图
- 类包含3个组成部分,第一栏为类名,第二栏为属性,第三栏为方法
- 属性和方法前可加一个可见性修饰符,
+
号表示 public
修饰符, -
号表示 private
修饰符, #
号表示 protected
修饰符,省略表示包级可见。
- 接口包含2个组成部分,第一栏为接口名,第二栏为方法,在接口名之上加上
<<interface>>
使用场景
比如游戏中一个用户的用过外挂违规次数属性,如果用户用过1~3次,每次警告制裁;3次以上,每次封号3天;5次以上,每次封号1周;到达10次,永久封号。
根据以上描述可以分为四种状态:
源码
环境角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| public class PunishManager {
private Map<String, Integer> mPunishMap = new HashMap<>();
Map<String, Integer> getPunishMap() { return mPunishMap; }
private PunishState getPunishState(Integer oldPunishCount) {
if (oldPunishCount <= 3) { return new LowPunishState(); }
if (oldPunishCount <= 5) { return new MidPunishState(); }
if (oldPunishCount < 10) { return new HeightPunishState(); }
return new BlackPunishState(); }
public void punish(String uid) { Integer oldPunishCount = mPunishMap.get(uid);
if (oldPunishCount == null) { oldPunishCount = 0; }
oldPunishCount += 1; mPunishMap.put(uid, oldPunishCount);
getPunishState(oldPunishCount).punish(uid, oldPunishCount, this); } }
|
抽象状态角色
1 2 3 4 5 6 7 8 9 10
| public interface PunishState {
public void punish(String uid, int violationCount, PunishManager punishManager); }
|
具体状态角色
根据不同的具体状态角色做相应的业务
1 2 3 4 5 6 7 8
| public class LowPunishState implements PunishState {
@Override public void punish(String uid, int violationCount, PunishManager punishManager) { System.out.println("警告制裁"); } }
|
1 2 3 4 5 6 7
| public class MidPunishState implements PunishState { @Override public void punish(String uid, int violationCount, PunishManager punishManager) { System.out.println("封号三天"); } }
|
1 2 3 4 5 6 7
| public class HeightPunishState implements PunishState { @Override public void punish(String uid, int violationCount, PunishManager punishManager) { System.out.println("封号一周"); } }
|
1 2 3 4 5 6 7
| public class BlackPunishState implements PunishState { @Override public void punish(String uid, int violationCount, PunishManager punishManager) { System.out.println("永久封号"); } }
|
入口类
1 2 3 4 5 6 7 8 9
| public class Main { public static void main(String[] args) { PunishManager punishManager = new PunishManager();
for (int i = 1; i <= 10; i++) { punishManager.punish("Kevin"); } } }
|
运行结果:
优点
- 封装了转换规则
- 结构清晰,提高可维护性
- 不同状态对应的不同行为放到单独类中,方便增加新的状态,只需改变对象状态即可改变对象行为
缺点
- 增加了类和对象的个数
- 状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
评论