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 }