状态
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
**状态模式(State)**经常用在带有状态的对象中。
什么是状态?我们以QQ聊天为例,一个用户的QQ有几种状态:
- 离线状态(尚未登录);
- 正在登录状态;
- 在线状态;
- 忙状态(暂时离开)。
如何表示状态?我们定义一个enum
就可以表示不同的状态。但不同的状态需要对应不同的行为,比如收到消息时:
1 2 3 4 5
| if (state == ONLINE) { } else if (state == BUSY) { reply("现在忙,稍后回复"); } else if ...
|
状态模式的目的是为了把上述一大串if...else...
的逻辑给分拆到不同的状态类中,使得将来增加状态比较容易。
例如,我们设计一个聊天机器人,它有两个状态:
对于未连线状态,我们收到消息也不回复:
1 2 3 4 5 6 7 8 9
| public class DisconnectedState implements State { public String init() { return "Bye!"; }
public String reply(String input) { return ""; } }
|
对于已连线状态,我们回应收到的消息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class ConnectedState implements State { public String init() { return "Hello, I'm Bob."; }
public String reply(String input) { if (input.endsWith("?")) { return "Yes. " + input.substring(0, input.length() - 1) + "!"; } if (input.endsWith(".")) { return input.substring(0, input.length() - 1) + "!"; } return input.substring(0, input.length() - 1) + "?"; } }
|
状态模式的关键设计思想在于状态切换,我们引入一个BotContext
完成状态切换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class BotContext { private State state = new DisconnectedState();
public String chat(String input) { if ("hello".equalsIgnoreCase(input)) { state = new ConnectedState(); return state.init(); } else if ("bye".equalsIgnoreCase(input)) { / 收到bye切换到离线状态: state = new DisconnectedState(); return state.init(); } return state.reply(input); } }
|
这样,一个价值千万的AI聊天机器人就诞生了:
1 2 3 4 5 6 7 8
| Scanner scanner = new Scanner(System.in); BotContext bot = new BotContext(); for (;;) { System.out.print("> "); String input = scanner.nextLine(); String output = bot.chat(input); System.out.println(output.isEmpty() ? "(no reply)" : "< " + output); }
|
试试效果:
1 2 3 4 5 6 7 8
| > hello < Hello, I'm Bob. > Nice to meet you. < Nice to meet you! > Today is cold? < Yes. Today is cold! > bye < Bye!
|