Observer模式(觀察者設計模式)
Observer 設計模式?
在Observer模式中,當觀察物件的狀態發生變化時,會通知給觀察者。Observer模式適用於根據物件狀態進行相應處理的場景。
Observer 並非主動觀察,而是被動觀察,實際可以又稱之為釋出-訂閱者模式
MVC Model、View、Controller,並且Model裡面的操作不依賴於具體形式的內部模型,通常情況下: 一個Model對應多個View,這裡也是使用Observer設計模式最多的地方
java中觀察者介面
在package java.util;下存在了Observer介面,按照二類定義模式,允許傳遞物件,以及附帶引數
void update(Observable o, Object arg);
- 使用注意:java.util.observer介面和java.util.observable類並不好用。理由很簡單,傳遞給java.util.observer介面的Subject角色必須是java.util.observable型別(或者它的子型別)的。但Java只能單一繼承,也就說如果Subject角色已經是某個類的子類了,那麼它將無法繼承java.util.observable類。(單個使用還是可以的)
理清職責
- 實現功能:根據不同的觀察者顯示字串的方式也不一樣!
|名字=======》》》說明 |Observer || 表示觀察者的介面 |NumberGenerator || 表示生成數值的物件的抽象類 |RandomNumberGenerator || 生成隨機數的類 |Digitobserver || 表示以數字形式顯示數值的類 |Graphobserver || 表示以簡單的圖示形式顯示數值的類 |Main || 測試程式行為的類
Observer呼叫順序問題: 當在Observer存在多個需要通知的方法時,方法一多,容易出現混亂,所以你這裡使用template設計模式將在Observer定義的使用順序,提前安排好, 那麼子類去實現就行了。出現更改呼叫順序的時機,只需要去Observer中檢視。
- 可替換性原則:
- 利用抽象類與介面從具體的類中抽象出方法 2.將例項作為引數傳遞到類中,或者在類的欄位中儲存例項時,不要使用具體的型別,而是使用抽象型別介面作為引數傳遞。
- 相關設計模式
◆Mediator模式 在Mediator模式中,有時會使用Observer 模式來實現Mediator角色與Colleague角色之間的通訊。 就“傳送狀態變化通知”這一點而言,Mediator模式與Observer模式是類似的。不過,兩種模式中,通知的目的和視角不同。 在Mediator模式中,雖然也會發送通知,不過那不過是為了對Colleague角色進行仲裁而已。 而在Observer模式中,將Subject角色的狀態變化通知給Observer角色的目的則主要是為了使Subject角色和Observer角色同步。
UML
類圖:
Code
- Observer 、NumberGenerator
public interface Observer {
/**
* 通知concreateObserver
* @param numberGenerator
*/
void update(NumberGenerator numberGenerator);
}
public abstract class NumberGenerator {
private List<Observer> observers=new ArrayList<>();
/**
* 增加觀察者
* @param observer
*/
public void addObserver(Observer observer){observers.add(observer);};
/**
* 移除觀察者
* @param observer
*/
public void deleteObserver(Observer observer){observers.remove(observer);};
/**
* 通知所有的觀察者
*/
protected void notifyObservers(){
Iterator<Observer> it = observers.iterator();
while (it.hasNext()){
Observer next = it.next();
next.update(this);
}
}
/**
* 獲取數值
*/
public abstract int getNumber();
/**
* 生成數值
*/
public abstract void excute();
}
- Graphobserver 、Digitobserver 兩個觀察者
public class Digitobserver implements Observer {
@Override
public void update(NumberGenerator numberGenerator) {
System.out.println(this.getClass().getName()+":"+numberGenerator.getNumber());
try {
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class Graphobserver implements Observer {
@Override
public void update(NumberGenerator numberGenerator) {
System.out.println(this.getClass().getName()+":");
for (int i = 0; i < numberGenerator.getNumber(); i++) {
System.out.print("*");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- RandomNumberGenerator
public class RandomNumberGenerator extends NumberGenerator{
private Random random=new Random();
private int number;
@Override
public int getNumber() {
return number;
}
/**
* 生成一次數值,通知一次觀察者
*/
@Override
public void excute() {
for (int i = 0; i < 20; i++) {
number=random.nextInt(50);
notifyObservers();
}
}
}
- MainT
public class MainT {
public static void main(String[] args) {
NumberGenerator generator = new RandomNumberGenerator();
// 觀察者
Digitobserver digitobserver = new Digitobserver();
Graphobserver graphobserver = new Graphobserver();
generator.addObserver(digitobserver);
generator.addObserver(graphobserver);
generator.excute();
}
}