8.1觀察者模式??????
8.1.1概念
? 觀察者模式定義了一種一對(duì)多的依賴關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主題對(duì)象,當(dāng)主題對(duì)象狀態(tài)發(fā)生變化時(shí),會(huì)通知所有依賴它的觀察者對(duì)象,使它們都能夠得到通知并且被自動(dòng)更新
8.1.2場(chǎng)景
? 在我們生活中,用戶可以在音樂播放平臺(tái)關(guān)注多個(gè)歌手,而當(dāng)有歌手發(fā)布新的歌曲時(shí),可以將歌曲發(fā)布到音樂播放平臺(tái),而平臺(tái)會(huì)將新的歌曲詳細(xì)信息發(fā)送給關(guān)注該歌手的用戶。而此時(shí)歌手就相當(dāng)于是觀察者模式的主題對(duì)象,每個(gè)關(guān)注的用戶則是觀察者模式中的觀察者對(duì)象,通過該模式,用戶可以很及時(shí)的聽到歌手的新歌曲,而歌手也可以很輕松的通知用戶新歌曲的發(fā)布。
8.1.3優(yōu)勢(shì) / 劣勢(shì)
- 靈活性:提供了靈活的觀察者注冊(cè)機(jī)制,可以隨時(shí)添加或刪除觀察者,使得系統(tǒng)更加靈活和可擴(kuò)展
- 自動(dòng)更新:當(dāng)被觀察者的狀態(tài)發(fā)生改變時(shí),所有依賴它的觀察者都會(huì)自動(dòng)收到通知并更新,提高了系統(tǒng)的自動(dòng)化程度
- 性能影響:當(dāng)被觀察者的狀態(tài)發(fā)生改變時(shí),所有觀察者都會(huì)收到通知并且進(jìn)行相應(yīng)的通知,可能導(dǎo)致大量的通知和計(jì)算,影響系統(tǒng)性能
- 通知競(jìng)態(tài)條件:若多個(gè)線程同時(shí)修改被觀察者的狀態(tài),可能會(huì)產(chǎn)生競(jìng)態(tài)條件,導(dǎo)致某些觀察者未能及時(shí)收到通知或收到錯(cuò)誤的通知
8.1.4觀察者模式可分為
- 主題Subject:就是被觀察的對(duì)象,可以維護(hù)一組觀察者,當(dāng)主題本身發(fā)生改變時(shí)就會(huì)通知觀察者
- 觀察者Observer:觀察主題的對(duì)象,當(dāng)"被觀察"的主題發(fā)生變化時(shí),觀察者就會(huì)得到通知并執(zhí)行相應(yīng)的處理
觀察者的基本結(jié)構(gòu):
- 主題Subject:一般會(huì)定義成一個(gè)接口,提供方法用于注冊(cè)、刪除、通知觀察者,通常也包含一個(gè)狀態(tài),當(dāng)狀態(tài)發(fā)生改變時(shí),通知所有的觀察者
- 觀察者Observer:觀察者也需要實(shí)現(xiàn)一個(gè)接口,包含一個(gè)更新方法,在接收主題通知時(shí)執(zhí)行對(duì)應(yīng)的操作
- 具體主題ConcreteSubject:主題的具體實(shí)現(xiàn),維護(hù)一個(gè)觀察者列表,包含了觀察者的注冊(cè)、刪除、通知方法
- 具體觀察者ConcreteObserver:觀察者接口的具體實(shí)現(xiàn),每個(gè)具體
8.1.5觀察者模式
package com.technologystatck.designpattern.mode.observer;
import java.util.ArrayList;
import java.util.List;
public class Observers {
public static void main(String[] args) {
//創(chuàng)建具體主題對(duì)象
ConcreteSubject concreteSubject = new ConcreteSubject();
//創(chuàng)建具體觀察者對(duì)象
Observer concreteObserverA = new ConcreteObserver();
Observer concreteObserverB = new ConcreteObserver();
//注冊(cè)觀察者
concreteSubject.registerObserver(concreteObserverA);
concreteSubject.registerObserver(concreteObserverB);
//調(diào)用主題方法
concreteSubject.setState("有新的觀察者注冊(cè)");
}
}
//主題接口(主題)
interface Subject{
//注冊(cè)觀察者
void registerObserver(Observer observer);
//移除觀察者
void removeObserver(Observer observer);
//通知觀察者
void notifyObserver();
}
//觀察者接口(觀察者)
interface Observer{
//更新方法
void update(String message);
}
//具體主題實(shí)現(xiàn)
class ConcreteSubject implements Subject{
//觀察者列表
private List<Observer> observers = new ArrayList<>();
//狀態(tài)
private String state;
//注冊(cè)觀察者方法(注冊(cè))
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
//移除觀察者方法(移除)
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
//通知觀察者方法(通知)
//遍歷觀察者列表,并通知每個(gè)觀察者更新狀態(tài)
@Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update(state);
}
}
//更新狀態(tài)
public void setState(String state) {
this.state = state;
notifyObserver();
}
}
//具體觀察者實(shí)現(xiàn)
class ConcreteObserver implements Observer{
//更新方法
@Override
public void update(String message) {
System.out.println(message);
}
}
8.1.6實(shí)戰(zhàn)
8.1.6.1題目描述
小明所在的學(xué)校有一個(gè)時(shí)鐘(主題),每到整點(diǎn)時(shí),它就會(huì)通知所有的學(xué)生(觀察者)當(dāng)前的時(shí)間,請(qǐng)你使用觀察者模式實(shí)現(xiàn)這個(gè)時(shí)鐘通知系統(tǒng)。
注意點(diǎn):時(shí)間從 0 開始,并每隔一個(gè)小時(shí)更新一次。
8.1.6.2輸入描述
輸入的第一行是一個(gè)整數(shù) N(1 ≤ N ≤ 20),表示學(xué)生的數(shù)量。
接下來的 N 行,每行包含一個(gè)字符串,表示學(xué)生的姓名。
最后一行是一個(gè)整數(shù),表示時(shí)鐘更新的次數(shù)。文章來源:http://www.zghlxwxcb.cn/news/detail-821433.html
8.1.6.3輸出描述
對(duì)于每一次時(shí)鐘更新,輸出每個(gè)學(xué)生的姓名和當(dāng)前的時(shí)間。文章來源地址http://www.zghlxwxcb.cn/news/detail-821433.html
8.1.6.4代碼
package com.technologystatck.designpattern.mode.observer;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 讀取學(xué)?數(shù)量
int N = scanner.nextInt();
// 創(chuàng)建時(shí)鐘
Clock clock = new Clock();
// 注冊(cè)學(xué)?觀察者
for (int i = 0; i < N; i++) {
String studentName = scanner.next();
clock.registerObserver(new Student(studentName));
}
// 讀取時(shí)鐘更新次數(shù)
int updates = scanner.nextInt();
// 模擬時(shí)鐘每隔?個(gè)?時(shí)更新?次
for (int i = 0; i < updates; i++) {
clock.tick();
}
}
}
// 觀察者接?
interface Observer {
void update(int hour);
}
// 主題接?
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具體主題實(shí)現(xiàn)
class Clock implements Subject {
private List<Observer> observers = new ArrayList<>();
private int hour = 0;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(hour);
}
}
public void tick() {
hour = (hour + 1) % 24; // 模擬時(shí)間的推移
notifyObservers();
}
}
// 具體觀察者實(shí)現(xiàn)
class Student implements Observer {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void update(int hour) {
System.out.println(name + " " + hour);
}
}
8.1.7總結(jié)
- 優(yōu)點(diǎn):可以靈活的增加 / 刪除觀察者對(duì)象,而不影響其他相關(guān)對(duì)象的功能
- 總結(jié):定義一對(duì)多的依賴關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一主題對(duì)象的狀態(tài)變化,實(shí)現(xiàn)自動(dòng)更新
- 場(chǎng)景:適用于一個(gè)對(duì)象的狀態(tài)變化會(huì)影響到其他對(duì)象,并且希望這些對(duì)象在狀態(tài)變化時(shí)能夠自動(dòng)更新的情況
到了這里,關(guān)于笨蛋學(xué)設(shè)計(jì)模式行為型模式-觀察者模式【14】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!