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();
}
}