设计模式State 的一个例子
(引自http://blog.csdn.net/airhand/archive/2004/08/27/86405.aspx?中的部分章节)
这个实例比较长,我简单说明一下,这是一个自动售货机的例子,客户可以投掷面值5、10、25的硬币,货物价值25。每当客户投了硬币就打印投的钱数和,如果够了25,就提示货物售出。
state是个抽象类,它派生了5、10、15、20、25几种钱数和的类(也就是所有可能的钱数和),由于它们都是从STATE继承的,所以它们都有一个STATE类型的静态成员state作为状态的标识(你可以把它想象成全局变量),每个类都接收投入5、10、25面值的硬币,对应的方法是
public virtual void AddNickel(VendingMachine vm) { }
public virtual void AddDime(VendingMachine vm) { }
public virtual void AddQuarter(VendingMachine vm) { }
虽然方法一样,但是每个类内部实现的状态跃迁是不一样的,比如5元的类,接收10元后state就跃迁到了15元,以此类推。
仔细看看吧,这是一个非常有意思的实例。不过说实话,这样实现程序确实太累了,也许在别的应用中可以降低程序员的负担,不过我还没发现(有的话告诉我)。
另外如果有100种状态,有10种路径,难道每个状态都要继承(100×10)?那coding起来岂不是太累,而且代码不要太长啊,唉,当程序员真不容易啊...
using System;
abstract class State {
? public virtual void AddNickel(VendingMachine vm) {}
? public virtual void AddDime(VendingMachine vm) {}
? public virtual void AddQuarter(VendingMachine vm) {}
? protected virtual void ChangeState(VendingMachine vm, State s) {
??? vm.ChangeState(s);
? }
}
class VendingMachine {
? private State state;
? public VendingMachine() {
??? Console.WriteLine("The Vending Machine is now online: product costs 25c");
??? state = Start.Instance();
? }
? public void ChangeState(State to) {
??? state = to;
? }
? public void Vend() {
// 发饮料
??? Console.WriteLine("Dispensing product...Thank you!");
? }
? public void AddNickel() {
??? state.AddNickel(this);
? }
? public void AddDime() {
??? state.AddDime(this);
? }
? public void AddQuarter() {
??? state.AddQuarter(this);
? }
}
class Start : State {
? private static State state = new Start();
? private Start() {
? }
? public static State Instance() {
// singleton逻辑
??? Console.WriteLine("Credit: 0c");
??? return state;
? }
? public override void AddNickel(VendingMachine vm) {
??? ChangeState(vm, Five.Instance());
? }
? public override void AddDime(VendingMachine vm) {
??? ChangeState(vm, Ten.Instance());
? }
? public override void AddQuarter(VendingMachine vm) {
??? vm.Vend();
? }
}
class Five : State {
? private static State state = new Five();
? private Five() {
? }
? public static State Instance() {
// singleton 逻辑
??? Console.WriteLine("Credit: 5c");
??? return state;
? }
? public override void AddNickel(VendingMachine vm) {
??? ChangeState(vm, Ten.Instance());
? }
? public override void AddDime(VendingMachine vm) {
??? ChangeState(vm, Fifteen.Instance());
? }
? public override void AddQuarter(VendingMachine vm) {
??? vm.Vend();
??? ChangeState(vm, Start.Instance()); // no change returned :-)
? }
}
class Ten : State {
? private static State state = new Ten();
? private Ten() {
? }
? public static State Instance() {
// singleton 逻辑
??? Console.WriteLine("Credit: 10c");
??? return state;
? }
? public override void AddNickel(VendingMachine vm) {
??? ChangeState(vm, Fifteen.Instance());
? }
? public override void AddDime(VendingMachine vm) {
??? ChangeState(vm, Twenty.Instance());
? }
? public override void AddQuarter(VendingMachine vm) {
??? vm.Vend();
??? ChangeState(vm, Start.Instance()); // no change returned :-)
? }
}
class Fifteen : State {
? private static State state = new Fifteen();
? private Fifteen() {
? }
? public static State Instance() {
// singleton 逻辑
??? Console.WriteLine("Credit: 15c");
??? return state;
? }
? public override void AddNickel(VendingMachine vm) {
??? ChangeState(vm, Twenty.Instance());
? }
? public override void AddDime(VendingMachine vm) {
??? vm.Vend();
??? ChangeState(vm, Start.Instance());
? }
? public override void AddQuarter(VendingMachine vm) {
??? vm.Vend();
??? ChangeState(vm, Start.Instance()); // no change returned :-)
? }
}
class Twenty : State {
? private static State state = new Twenty();
? private Twenty() {
? }
? public static State Instance() {
// singleton 逻辑
??? Console.WriteLine("Credit: 20c");
??? return state;
? }
? public override void AddNickel(VendingMachine vm) {
??? vm.Vend();
??? ChangeState(vm, Start.Instance());
? }
? public override void AddDime(VendingMachine vm) {
??? vm.Vend();
??? ChangeState(vm, Start.Instance());
? }
? public override void AddQuarter(VendingMachine vm) {
??? vm.Vend();
??? ChangeState(vm, Start.Instance()); // no change returned :-)
? }
}
class Application {
? public static void Main() {
??? int coin = 0;
??? string input = null;
??? VendingMachine vm = new VendingMachine();
??? while (true) {
????? Console.Write("Insert a coin (5, 10, 25): ");
????? input = Console.ReadLine();
????? coin = Int32.Parse(input);
????? switch (coin) {
??????? case 5:
????????? vm.AddNickel();
????????? break;
??????? case 10:
????????? vm.AddDime();
????????? break;
??????? case 25:
????????? vm.AddQuarter();
????????? break;
??????? default:
????????? break;
????? }
??? }
? }
}