/* BoundedCounter.java ** Abstract Java class that extends ResetableCounter. An instance of this ** class is such that its count value is restricted to lie within a range ** of integers whose lower and upper bounds (called 'floor' and 'ceiling', ** respectively) are specified upon construction. ** The effect of incrementing (respectively, decrementing) a BoundedCounter ** is the same as with a ResetableCounter, except when its count value is ** equal to its ceiling (resp., floor). In that case, the effect is that ** caused by the abstract method incrementFromCeiling() (resp., ** decrementFromFloor()) and thus is left to be specified by each subclass. */ public abstract class BoundedCounter extends ResetableCounter { // instance variables // ------------------ private final int floor; // minimum allowed count value private final int ceiling; // maximum allowed count value // constructors // ------------ /* Initializes this BoundedCounter so that its range of possible ** count values is min..max and its initial value is init. ** An IllegalArgumentException is thrown if the condition ** min <= init <= max is not satisfied. ** ** pre: min <= init <= max (or else an exception is thrown) ** post: this.countVal() == init && ** this.floor() == min && ** this.ceiling() == max */ public BoundedCounter(int init, int min, int max) { super(init); if (init < min || init > max) { throw new IllegalArgumentException("Condition min <= init <= max violated"); } floor = min; ceiling = max; } /* Initializes this BoundedCounter so that its range of possible ** count values is min..max and its initial value is min. ** pre: min <= max ** post: this.countVal() == min && ** this.floor() == min && ** this.ceiling() == max */ public BoundedCounter(int min, int max) { this(min, min, max); } // observers // --------- public int floorOf() { return floor; } public int ceilingOf() { return ceiling; } @Override public String toString() { return "count value:" + countVal() + "; floor:" + floorOf() + "; ceiling:" + ceilingOf() + "; initial value:" + initialVal(); } // mutators // -------- /* Increments this BoundedCounter's count value, which means applying the ** inherited version of the method except when the count value equals ** this.ceiling(), in which case the incrementFromCeiling() method is ** applied. */ @Override public void increment() { if (countVal() == ceiling) { incrementFromCeiling(); } else { super.increment(); } } /* Decrements this BoundedCounter's count value, which means applying the ** inherited version of the method except when the count value equals ** this.floorOf(), in which case the decrementFromFloor() method is applied. */ @Override public void decrement() { if (countVal() == floor) { decrementFromFloor(); } else { super.decrement(); } } // mutators (abstract, and thus left for descendant classes to implement) // -------- /* Takes appropriate action to increment this BoundedCounter's count value ** in the case that it currently equals ceilingOf(); */ protected abstract void incrementFromCeiling(); /* Takes appropriate action to decrement this BoundedCounter's count value ** in the case that it currently equals floorOf(); */ protected abstract void decrementFromFloor(); }