一對多關係(Subject & Observer),實際資料位於主題(Subject)中,觀察者依附於主題,只要主題資料有更動,觀察者也會一併被通知
主題類別(要發送訊息的類別實作它)

  public interface Subject {//主題
      public void registerObserver(Observer ob);// 註冊觀察者
      public void removeObserver(Observer ob);// 移除觀察者
      public void notifyObservers();// 通知所有觀察者資料變動
  }

 
觀察者類別(要接收訊息的類別實作它)

  import java.util.ArrayList;
  interface Observer {// 觀察者
      public void updateNum(ArrayList<Integer> al);// 所有觀察者更新資料
  }

 

樂透開獎機(這是我的主題)

  import java.util.ArrayList;
  import java.util.Random;
  public class LottoSystem implements Subject, Runnable {// Runnable只用於方便開獎,沒有其他用途
      ArrayList<Observer> obsal;// 存放所有觀察者
      ArrayList<Integer> numberal;// 存放樂透數字
      public LottoSystem() {
          obsal = new ArrayList<Observer>();
          numberal = new ArrayList<Integer>();
          for (int i = 0; i < 6; i++) {// 初始 6 個號碼為 0
              numberal.add(0);
          }
      }
      public void registerObserver(Observer ob) {
          obsal.add(ob);
      }
      public void removeObserver(Observer ob) {
          int i = obsal.indexOf(ob);
          if (i >= 0) {
              obsal.remove(i);
          }
      }
      // 主題更新資料之後,必須呼叫此方法以通知所有觀察者
      public void notifyObservers() {
          for (int i = 0; i < obsal.size(); i++) {
              Observer ob = (Observer) obsal.get(i);
              ob.updateNum(numberal);
          }
      }
      public void lottery() {
          Random r = new Random();
          for (int i = 0; i < numberal.size(); i++) {
              int tempnum = r.nextInt(48);
              for (int j = 0; j < numberal.size(); j++) {
                  if (tempnum == numberal.get(j) && i != j) {
                      tempnum = r.nextInt(48);
                      j = 0;
                      i = 0;
                  }
              }
              numberal.set(i, tempnum);
          }
          notifyObservers();
      }
      // 模擬開獎
      public void run() {
          while (true) {
              lottery();
              try {
                  Thread.currentThread().sleep(1500);
              } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
          }
      }
  }

 

這是購買樂透的人(也是觀察者)

  import java.util.ArrayList;
  public class ShowLottoNum implements Observer {
      String name;
      ArrayList<Integer> numlist;// 存放樂透數字
      Subject s;// 主題,用來註冊該觀察者
      // 當觀察者建構自己必須傳入已存在的主題物件以註冊自己本身
      public ShowLottoNum(Subject s, String name) {
          this.s = s;
          s.registerObserver(this);
          this.name = name;
      }
      @Override
      public void updateNum(ArrayList<Integer> al) {
          // TODO Auto-generated method stub
          numlist = al;
          showNum();
      }
      public void showNum() {
          System.out.print(name + " get number :");
          for (int i = 0; i < numlist.size(); i++) {
              System.out.print(numlist.get(i) + ",");
          }
          System.out.println();
      }
  }

測試程式

  import java.util.ArrayList;
  import java.util.List;
  public class Simulator {
      public static void main(String[] args) {
          LottoSystem ls = new LottoSystem();// 主題
          ShowLottoNum sln = new ShowLottoNum(ls, "John");// 觀察者1(若需要更多觀察者,只要照著
                                                          // ShowLottoNum 建構即可 )
          ShowLottoNum sln2 = new ShowLottoNum(ls, "Peter");// 觀察者2
          ShowLottoNum sln3 = new ShowLottoNum(ls, "Little flower");// 觀察3
          // 開始開獎
          new Thread(ls).start();
      }
  }