// Purpose.  Mediator design pattern

// 1. Create an "intermediary" that decouples "senders" from "receivers"
// 2. Producers are coupled only to the Mediator
// 3. Consumers are coupled only to the Mediator
// 4. The Mediator arbitrates the storing and retrieving of messages

class Mediator {                        // 1. The "intermediary"
   private boolean slotFull = false;    // 4. The Mediator arbitrates
   private int     number;
   public synchronized void storeMessage( int num ) {
      while (slotFull == true)          // no room for another message
         try { wait(); } catch (InterruptedException e ) { }
      slotFull = true;
      number = num;
      notifyAll();
   }
   public synchronized int retrieveMessage() {
      while (slotFull == false)         // no message to retrieve
         try { wait(); } catch (InterruptedException e ) { }
      slotFull = false;
      notifyAll();
      return number;
}  }

class Producer extends Thread {
   private Mediator med;                // 2. Producers are coupled only to
   private int      id;                 //    the Mediator
   private static int num = 1;
   public Producer( Mediator m ) { med = m;  id = num++; }
   public void run() {
      int num;
      while (true) {
         med.storeMessage( num = (int)(Math.random()*100) );
         System.out.print( "p" + id + "-" + num + "   " );
}  }  }

class Consumer extends Thread {
   private Mediator med;                // 3. Consumers are coupled only to
   private int      id;                 //    the Mediator
   private static int num = 1;
   public Consumer( Mediator m ) { med = m;  id = num++; }
   public void run() {
      while (true) {
         System.out.print( "c" + id + "-" + med.retrieveMessage() + "   " );
}  }  }

class MediatorDemo {
   public static void main( String[] args ) {
      Mediator mb = new Mediator();
      new Producer( mb ).start();
      new Producer( mb ).start();
      new Consumer( mb ).start();
      new Consumer( mb ).start();
      new Consumer( mb ).start();
      new Consumer( mb ).start();
}  }

// p1-87   c1-87   p2-37   c3-37   p1-28   c2-28   p2-58   c1-58   p1-18   c4-18
// p2-42   c3-42   p1-3   c2-3   p2-11   c3-11   p1-72   c2-72   p2-75   c3-75
// p1-93   c4-93   p2-52   c1-52   p1-21   c3-21   p2-80   c4-80   p1-96   c2-96