001 package counter;
002
003 import logic.*;
004
005 public class CounterFactory implements ICounterFactory {
006
007 public static final CounterFactory Singleton = new CounterFactory();
008 private CounterFactory() {}
009
010 private static abstract class ACounterState {
011 abstract ICounter decrement();
012 abstract ICounter increment();
013 abstract Object execute(ICounterAlgo algo, Object... param);
014 }
015
016
017 public ICounter makeCounter(final int aCount) {
018 return new ICounter() {
019 private IBooleanAlgo setCountAlgo = new IBooleanAlgo() {
020 public Object trueCase(IBoolean host, Object... param) {
021 counterState = zeroState;
022 return null;
023 }
024 public Object falseCase(IBoolean host, Object... param) {
025 counterState = nonZeroState;
026 return null;
027 }
028 };
029
030 private ICounter thisCounter = this; // hack to get self-reference
031
032 private ACounterState zeroState = new ACounterState() {
033 ICounter decrement() {
034 count = -1;
035 counterState = nonZeroState;
036 return thisCounter;
037 }
038
039 ICounter increment(){
040 count = 1;
041 counterState = nonZeroState;
042 return thisCounter;
043 }
044
045 Object execute(ICounterAlgo algo, Object... param) {
046 return algo.zeroCase(thisCounter,param);
047 }
048 };
049
050 private ACounterState nonZeroState = new ACounterState() {
051 ICounter decrement() {
052 return setCount(--count);
053 }
054
055 ICounter increment(){
056 count++;
057 return thisCounter;
058 }
059
060 Object execute(ICounterAlgo algo, Object... param) {
061 return algo.nonZeroCase(thisCounter,param);
062 }
063 };
064
065 private int count = aCount;
066 private ACounterState counterState = zeroState;
067
068 /**
069 * Initializer block
070 * Must come after the fields are initialized so to avoid null ptr errors.
071 */
072 {
073 setCount(aCount); // initialize the counter
074 }
075
076
077 public ICounter decrement() {
078 return counterState.decrement();
079 }
080
081 public ICounter increment() {
082 return counterState.increment();
083 }
084
085 public int getCount() {
086 return count;
087 }
088
089 public ICounter setCount(int newCount) {
090 count = newCount;
091 BooleanFactory.Singleton.makeBoolean(0==count).execute(setCountAlgo);
092 return this;
093 }
094
095 public Object execute(ICounterAlgo algo, Object... param) {
096 return counterState.execute(algo, param);
097 }
098
099 };
100 }
101 }