设计模式(十七)Observer模式

  在Observer模式中,当观察对象的状态发生变化时,会通知给观察者。Observer模式适用于根据对象状态进行相应处理的场景。

  首先看一下示例程序的视图。

 

  然后用实际代码来理解这种设计模式。

1 package bigjunoba.bjtu.observer;
2 
3 public interface Observer {
4 
5     public abstract void update(NumberGenerator generator);
6 }

  Observer接口是用来表示“观察者”的接口。具体的观察者会实现这个接口。用于生成数值的NumberGenerator类会调用update方法。如果调用update方法,NumberGenerator类就会将“生成的数值发生了变化,请更新显示内容”的通知发送给Observer。

 1 package bigjunoba.bjtu.observer;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Iterator;
 5 
 6 public abstract class NumberGenerator {
 7 
 8     private ArrayList<Observer> observers = new ArrayList<>();
 9     
10     public void addObserver(Observer observer) {
11         observers.add(observer);
12     }
13     
14     public void deleteObserver(Observer observer) {
15         observers.remove(observer);
16     }
17     
18     public void notifyObservers() {
19         Iterator<Observer> iterator = observers.iterator();
20         while (iterator.hasNext()) {
21             Observer observer = (Observer) iterator.next();
22             observer.update(this);
23         }
24     }
25     
26     public abstract int getNumber();
27     public abstract void excute();
28 
29 }

  NumberGenerator类是用于生成数值的抽象类。生成数值的excute方法和获取数值的getNumber方法都是抽象方法,需要子类去实现。observers字段中保存有观察NumberGenerator的Observer们。notifyObservers方法会向所有的Observer发送通知,告诉他们“我生成的数值发生了变化,请更新显示内容”。该方法会调用每个Observer的update方法。

 1 package bigjunoba.bjtu.observer;
 2 
 3 import java.util.Random;
 4 
 5 public class RandomNumberGenetor extends NumberGenerator {
 6     
 7     private Random random = new Random();
 8     private int number;
 9     
10     @Override
11     public int getNumber() {
12         return number;
13     }
14 
15     @Override
16     public void excute() {
17         for (int i = 0; i < 10; i++) {
18             number = random.nextInt(50);
19             notifyObservers();
20         }
21     }
22 }

  RandomNumberGenetor类是NumberGenerator的子类。excute方法会生成10个随机数,并通过notifyObservers方法把每次生成的结果通知给观察者。

 1 package bigjunoba.bjtu.observer;
 2 
 3 public class DigitObserver implements Observer {
 4 
 5     @Override
 6     public void update(NumberGenerator generator) {
 7         System.out.println("DigitObserver:" + generator.getNumber());
 8         try {
 9             Thread.sleep(100);
10         } catch (InterruptedException e) {
11         }
12     }
13 }

  DigitObserver类作为第一个观察者,它的功能是以数字形式显示观察到的数值。为了能看清它是如何显示数值的,使用Thread.sleep(100)来降低程序的运行速度。

 1 package bigjunoba.bjtu.observer;
 2 
 3 public class GraphObserver implements Observer {
 4 
 5     @Override
 6     public void update(NumberGenerator generator) {
 7         System.out.println("GraphObserver:");
 8         
 9         int count = generator.getNumber();
10         for (int i = 0; i < count; i++) {
11             System.out.print("*");
12         }
13         
14         System.out.println("");
15         
16         try {
17             Thread.sleep(100);
18         } catch (InterruptedException e) {
19         }
20     }
21 }

  GraphObserver类作为第二个观察者,功能是将观察到的数值以****表示出来。

 1 package bigjunoba.bjtu.observer;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         NumberGenerator generator = new RandomNumberGenetor();
 6         Observer observer1 = new DigitObserver();
 7         Observer observer2 = new GraphObserver();
 8         generator.addObserver(observer1);
 9         generator.addObserver(observer2);
10         generator.excute();
11     }
12 }

  Main类作为测试类。首先生成了RandomNumberGenerator类的实例保存在NumberGenerator类的generator字段中,然后生成两个观察者实例,然后将观察者注册之后,调用每一个观察者的update方法。

DigitObserver:20
GraphObserver:
********************
DigitObserver:46
GraphObserver:
**********************************************
DigitObserver:10
GraphObserver:
**********
DigitObserver:45
GraphObserver:
*********************************************
DigitObserver:10
GraphObserver:
**********
DigitObserver:5
GraphObserver:
*****
DigitObserver:37
GraphObserver:
*************************************
DigitObserver:24
GraphObserver:
************************
DigitObserver:34
GraphObserver:
**********************************
DigitObserver:30
GraphObserver:
******************************

   测试结果如上图所示。

  这里不作过多解释。因为这种设计模式还是很容易理解的。

posted @ 2018-04-12 08:57  BigJunOba  阅读(222)  评论(0编辑  收藏  举报