// @topic S-0314-13-04-40 Java Iterator and Visitor patterns // @brief class Floor implements IVisitable, IUpdatable package week11; import java.util.ArrayList; import java.util.Iterator; public class Floor implements IVisitable, IUpdatable { // collection of visitors currently visiting the floor: private ArrayList< Visitor > visitors = new ArrayList(); // iterator helper object to allow visitor // removal from the collection of visitors // during the update loop: Iterator<Visitor> visitorIterator = null; // A visitor who is currently being updated // and may potentially want to remove itself // from the collection of visitors: Visitor removalCandidate = null; //------------------------------------------ // operations //------------------------------------------ // IVisitable implemention // A visitor wants to be accepted by the floor: @Override public boolean accept( Visitor visitor ) { visitors.add( visitor ); return true; } // A visitor wants to leave the floor: @Override public boolean forget( Visitor visitor ) { if ( removalCandidate == visitor ) { // in the middle of an update loop // we can only remove the visitor // being currently updated: visitorIterator.remove(); } else if ( visitorIterator == null ) { // outside of update loop it is // ok to remove any visitor: visitors.remove( visitor ); } else { // sorry buddy, you cannot leave this floor // at this time for technical reasons, // "the system is too busy": return false; } return true; } // IUpdatable implemention // Scenario notifying the floor object // that a new visitor has arrived: @Override public void visitorArrived( Visitor visitor ) { visitor.visitorArrived(this); } // A floor object notifying the visitor // that "you are here": @Override public void visitorArrived( Floor floor ) {/*ignore*/} // Generic update from the background thread: @Override public void update() { // Solution (1) -- not good: // if content of collection is modified // during the update, // java.util.ConcurrentModificationException // is very likely!! //for ( Visitor visitor : visitors ) { // visitor.update(); //} // Solution (2) -- same problem: //Iterator<Visitor> it = visitors.iterator(); //while ( it.hasNext() ) { // Visitor visitor = it.next(); // visitor.update(); //} // Solution (3) -- keep iterator // as a member variable of this class: visitorIterator = visitors.iterator(); while ( visitorIterator.hasNext() ) { removalCandidate = visitorIterator.next(); removalCandidate.update(); } // both references set to null to indicate // that generic update is over: visitorIterator = null; removalCandidate = null; } // Elevator notifying the floor and visitor objects // about the elevator arrival: @Override public void elevatorArrived( /*Elevator elevator*/ ) {/*TODO*/} // Special update to all objects, // possibly a random event generated // by the scenario or the user pressing // the "red button" during the simulation: @Override public void emergency() {} }