写的比较晚了,贴代码供参考
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;
}
}
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{
@Override
double 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{
@Override
double 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 overrided
public 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;
@Override
public State state() {
// TODO Auto-generated method stub
return state;
}
@Override
public void state(State state) {
this.state = state;
}
}