JAVA枚举类状态机 与 Java枚举策略模式

来源:互联网 发布:淘宝账号怎么注销? 编辑:程序博客网 时间:2024/04/29 07:00

写的比较晚了,贴代码供参考


1、普通的enum方法设计如下,缺点是不方便维护,因为是switch语句,容易在扩展的时候忘了改相关的代码。但如果你的代码千年不变,这个缺点就不明显。

注意:测试结果参见第2点。

package enumclass;public enum PayrollBySwitch {Monday,Tuesday,Wendsday,Thursday,Friday,Saturday,Sunday;private static final int FIXED_WORK_HOUR_PER_DAY = 8;//加班工资会是基本工资的一半。private static final double OVER_TIME_PAY_RATE = 1/2;  public double pay(double workHours, double payPerHour){double basePay = workHours  * payPerHour;double overTimePay = 0;switch(this){//周六日每个小时都算加班工资case Saturday: case Sunday:overTimePay = workHours * payPerHour * OVER_TIME_PAY_RATE;break;default:overTimePay = workHours <= FIXED_WORK_HOUR_PER_DAY ?       0 : workHours - FIXED_WORK_HOUR_PER_DAY;break;}return basePay+overTimePay;}}

2、enum方法的改进版,使用了enum strategy模式。要点:

1、设计一个private的enum,作为strategy的抽象。

2、顶层enum的构造器需要传入策略PayType。

3、策略类需要定义一个抽象类,让private enum去实现这个方法。这里用到enum的另一个特性:特定于常量的方法(Constant-specific class body的Constant -specific method implementation)。

package enumclass;public enum PayrollByEnumStrategy {Monday(PayType.WeekDay),Tuesday(PayType.WeekDay),Wendsday(PayType.WeekDay),Thursday(PayType.WeekDay),Friday(PayType.WeekDay),Saturday(PayType.WeekEnd),Sunday(PayType.WeekEnd);PayType payType;private PayrollByEnumStrategy(PayType payType) {this.payType = payType;}public double pay(double workHours, double payPerHour){return payType.pay(workHours, payPerHour);}private enum PayType{WeekDay{@Overridedouble overTimePay(double workHours, double payPerHour) {double overTimePay = workHours <= FIXED_WORK_HOUR_PER_DAY ?       0 : (workHours - FIXED_WORK_HOUR_PER_DAY)*payPerHour*OVER_TIME_PAY_RATE;return overTimePay;}},WeekEnd{@Overridedouble overTimePay(double workHours, double payPerHour) {double overTimePay = workHours * payPerHour * OVER_TIME_PAY_RATE;return overTimePay;}};private static final int FIXED_WORK_HOUR_PER_DAY = 8;//加班工资会是基本工资的一半。private static final double OVER_TIME_PAY_RATE = 1/2;abstract double overTimePay(double workHours, double payPerHour);public double pay(double workHours, double payPerHour){double basePay = workHours  * payPerHour;double overTimePay = overTimePay(workHours,payPerHour);return basePay+overTimePay;}}}

1 和 2的测试结果:

工资总额 by Switch= ¥3510.0
工资总额 by Enum Strategy= ¥3510.0

测试类如下:

package enumclass;public class WorkPayment {public static void main(String[] args) {// TODO Auto-generated method stub//计算一周的工资总额——每天工作10小时,每小时400块。double sum = 0;for(PayrollBySwitch day : PayrollBySwitch.values()){sum += day.pay(10, 50);}System.out.println("工资总额 by Switch= ¥"+sum);sum = 0;for(PayrollBySwitch day : PayrollBySwitch.values()){sum += day.pay(10, 50);}System.out.println("工资总额 by Enum Strategy= ¥"+sum);}}


3、覆盖enum的toString带来的方便。

如下面例子,打印日志时,很方便

package enumclass;//enum strategy with toString overridedpublic enum Operation {  PLUS("*")   { double eval(double x, double y) { return x + y; } },  MINUS("-")  { double eval(double x, double y) { return x - y; } },  TIMES("*")  { double eval(double x, double y) { return x * y; } },  DIVIDE ("/"){ double eval(double x, double y) { return x / y; } };  String symbol = null;  Operation(String symbol){  this.symbol = symbol;  }  public String toString(){  return symbol;  }    // Do arithmetic op represented by this constant  abstract double eval(double x, double y); }
测试类
package enumclass;public class OperationTest {   public static void main(String[] args) {  double x = 2.000;  double y = 4.0000;    for(Operation oper : Operation.values()){  System.out.printf("%f %s %f = %f%n",x,oper,y,oper.eval(x, y));  }  }}

测试结果如下:

2.000000 * 4.000000 = 6.000000
2.000000 - 4.000000 = -2.000000
2.000000 * 4.000000 = 8.000000
2.000000 / 4.000000 = 0.500000


4、最后是状态机的实现,已上传。

要点:

1、enum可以实现interface。

2、状态机维护需要两种对象:Context上下文、States状态

3、Context管理State。

4、用while运行状态机,其实这个while放到Context内更好,应该是状态机自己维护状态,而不是外部通过状态机去控制状态。

5、比较巧的设计是,每个state的操作返回boolean,作为状态是否终止的判断。

资源:http://download.csdn.net/detail/xzongyuan/9871848

State设置为如下时:

context.state(States.WHITE);

运行结果:

Current State = WHITE
Current State = BLUE


package enumstatemachin;public class InfiniteMachineTest {public static void main(String[] args) {Context context = new ContextImp();context.state(States.WHITE);     while(context.state().process(context));}}
package enumstatemachin;import java.nio.ByteBuffer;enum States implements State {    RED {        public boolean process(Context context) {            context.state(States.GREEN);            System.out.println("Current State = " + this);            return true;        }    }, GREEN {        public boolean process(Context context) {            context.state(States.BLACK);            System.out.println("Current State = " + this);            return true;        }    },BLACK {        public boolean process(Context context) {            context.state(States.YELLOW);            System.out.println("Current State = " + this);            return true;        }    },YELLOW {        public boolean process(Context context) {            context.state(States.WHITE);            System.out.println("Current State = " + this);            return true;        }    },WHITE {        public boolean process(Context context) {            context.state(States.BLUE);            System.out.println("Current State = " + this);            return true;        }    },BLUE{    public boolean process(Context context) {    context.state(States.RED);            System.out.println("Current State = " + this);return false;    }      };public abstract boolean process(Context context);}

package enumstatemachin;interface State {    /**       * @return true to keep processing, false to read more data.     */    boolean process(Context context);}
package enumstatemachin;import java.nio.ByteBuffer;public interface Context {    State state();    void state(State state);}

package enumstatemachin;import java.nio.ByteBuffer;public class ContextImp implements Context {State state;@Overridepublic State state() {// TODO Auto-generated method stubreturn state;}@Overridepublic void state(State state) {this.state = state;}}





原创粉丝点击