java設(shè)計(jì)模式之觀察者模式簡(jiǎn)單解讀
前言
首先,弄明白兩組概念: 觀察者(Observer)與被觀察者(subject)、發(fā)布者(publicsher)與訂閱者(subscriber)。這是相似的兩組概念,講的時(shí)候,要對(duì)應(yīng)于各自所在的組,不要弄混了。
在對(duì)象之間定義了一對(duì)多的依賴(lài),這樣一來(lái),當(dāng)一個(gè)對(duì)象改變狀態(tài),依賴(lài)它的對(duì)象會(huì)收到通知并自動(dòng)更新。(這和前端vue的思想相同) 觀察者模式說(shuō)白了,其實(shí)就是發(fā)布訂閱模式,發(fā)布者發(fā)布信息,訂閱者獲取信息,訂閱了就能收到信息,沒(méi)訂閱就收不到信息。
思路
- 抽象出觀察者接口
- 抽象出被觀察者接口
- 觀察者類(lèi)實(shí)現(xiàn)觀察者接口
- 被觀察者類(lèi)實(shí)現(xiàn)被觀察者接口(被觀察者持有觀察者的一個(gè)隊(duì)列)
具體實(shí)現(xiàn)
實(shí)現(xiàn)時(shí),可以不一步到位,在遇到問(wèn)題的時(shí)候,你也許就知道該怎么做了
package com.wanmei.meishu.ms;
import java.util.ArrayList;
import java.util.List;
//觀察者接口
interface Observable{
//觀察
void addSub(ISubject sub);
//取消觀察
void removeSub(ISubject sub,String msg);
//讀取消息
void watch(String msg);
//獲取觀察者名稱(chēng)
String getName();
}
//觀察者實(shí)例
class Observer implements Observable {
private String name;
public Observer(String name) {
this.name = name;
}
@Override
public void addSub(ISubject sub){
sub.addObserver(this);
System.out.println("Observer:用戶(hù)【"+this.name+"】 訂閱了消息");
}
@Override
public void removeSub(ISubject sub,String msg){
sub.removeObserver(this);
System.out.println("Observer:用戶(hù)【"+this.name+"】 取消了訂閱消息," + (msg == null ? "" : ("并說(shuō):" + msg)));
}
@Override
public void watch(String msg) {
System.out.println("Observer:用戶(hù)【"+this.name+"】讀取到的訂閱消息是:" + msg);
}
public String getName() {
return name;
}
}
//被觀察者接口
interface ISubject{
//給觀察者們發(fā)送消息
void sendMsg(String msg);
//添加一個(gè)觀察者
void addObserver(Observable user);
//取消一個(gè)觀察者
void removeObserver(Observable user);
}
//被觀察者實(shí)現(xiàn)方式
class SubjectImpl implements ISubject{
//持有觀察者隊(duì)列
private List<Observable> observerList;
//添加一個(gè)觀察者
public synchronized void addObserver(Observable user){
if(observerList == null){
observerList = new ArrayList<Observable>();
}
observerList.add(user);
String str = "";
for (Observable observable : observerList) {
str+= observable.getName()+"、";
}
System.out.println("ISubject:目前已有用戶(hù):" + str.substring(0, str.length()-1));
}
//取消一個(gè)觀察者
public void removeObserver(Observable user){
observerList.remove(user);
if(!observerList.isEmpty()){
String str = "";
for (Observable observable : observerList) {
str+= observable.getName()+"、";
}
System.out.println("ISubject:目前剩余用戶(hù):" + str.substring(0, str.length()- 1));
}
}
@Override
public void sendMsg(String msg) {
if(!observerList.isEmpty()){
System.out.println("ISubject:發(fā)送消息:" + msg);
for (Observable observable : observerList) {
observable.watch(msg);
}
}
}
}
public class ObserverTest {
public static void main(String[] args) {
ISubject sub = new SubjectImpl();
//第一個(gè)觀察者
Observable u1 = new Observer("吳文俊");
u1.addSub(sub);
Observable u2 = new Observer("吳華云");
u2.addSub(sub);
Observable u3 = new Observer("李爪哇");
u3.addSub(sub);
sub.sendMsg("PHP是世界上最好的語(yǔ)言!");
u3.removeSub(sub,"去死吧,PHP");
sub.sendMsg("PHP是世界上最好的語(yǔ)言!");
}
}
運(yùn)行結(jié)果:
ISubject:目前已有用戶(hù):吳文俊
Observer:用戶(hù)【吳文俊】 訂閱了消息
ISubject:目前已有用戶(hù):吳文俊、吳華云
Observer:用戶(hù)【吳華云】 訂閱了消息
ISubject:目前已有用戶(hù):吳文俊、吳華云、李爪哇
Observer:用戶(hù)【李爪哇】 訂閱了消息
ISubject:發(fā)送消息:PHP是世界上最好的語(yǔ)言!
Observer:用戶(hù)【吳文俊】讀取到的訂閱消息是:PHP是世界上最好的語(yǔ)言!
Observer:用戶(hù)【吳華云】讀取到的訂閱消息是:PHP是世界上最好的語(yǔ)言!
Observer:用戶(hù)【李爪哇】讀取到的訂閱消息是:PHP是世界上最好的語(yǔ)言!
ISubject:目前剩余用戶(hù):吳文俊、吳華云
Observer:用戶(hù)【李爪哇】 取消了訂閱消息并說(shuō):去死吧,PHP
ISubject:發(fā)送消息:PHP是世界上最好的語(yǔ)言!
Observer:用戶(hù)【吳文俊】讀取到的訂閱消息是:PHP是世界上最好的語(yǔ)言!
Observer:用戶(hù)【吳華云】讀取到的訂閱消息是:PHP是世界上最好的語(yǔ)言!
到此這篇關(guān)于java設(shè)計(jì)模式之觀察者模式簡(jiǎn)單解讀的文章就介紹到這了,更多相關(guān)java觀察者模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot Actuator監(jiān)控端點(diǎn)小結(jié)
這篇文章主要介紹了Spring Boot Actuator監(jiān)控端點(diǎn)小結(jié),需要的朋友可以參考下2017-06-06
java面試LruCache?和?LinkedHashMap及算法實(shí)現(xiàn)
這篇文章主要為大家介紹了java面試LruCache?和?LinkedHashMap及算法實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
springboot啟動(dòng)時(shí)如何指定spring.profiles.active
這篇文章主要介紹了springboot啟動(dòng)時(shí)如何指定spring.profiles.active問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Mybatis中關(guān)于自定義mapper.xml時(shí),參數(shù)傳遞的方式及寫(xiě)法
這篇文章主要介紹了Mybatis中關(guān)于自定義mapper.xml時(shí),參數(shù)傳遞的方式及寫(xiě)法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
IDEA中WebService生成Java代碼并調(diào)用外部接口實(shí)現(xiàn)代碼
這篇文章主要介紹了IDEA中WebService生成Java代碼并調(diào)用外部接口實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05
如何在SpringBoot項(xiàng)目里進(jìn)行統(tǒng)一異常處理
這篇文章主要介紹了如何在SpringBoot項(xiàng)目里進(jìn)行統(tǒng)一異常處理,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值。需要的小伙伴可以參考一下2022-07-07
Spring Boot延遲執(zhí)行實(shí)現(xiàn)方法
本文介紹了在Spring Boot項(xiàng)目中延遲執(zhí)行方法的實(shí)現(xiàn),以及延遲執(zhí)行下聲明式事務(wù)和編程式事務(wù)的使用情況,感興趣的朋友一起看看吧2020-12-12
SpringBoot實(shí)現(xiàn)配置文件加密的方案分享
項(xiàng)目的數(shù)據(jù)庫(kù)密碼、redis 密碼等明文展示在配置文件中會(huì)有潛在的風(fēng)險(xiǎn),因此采用合適的安全防護(hù)措施是有必要的,下面小編就為大家介紹一下SpringBoot中配置文件加密的方法,希望對(duì)大家有所幫助2023-11-11
Java計(jì)算兩個(gè)時(shí)間相差的秒數(shù)怎么算
這篇文章主要介紹了Java計(jì)算兩個(gè)時(shí)間相差的秒數(shù),通過(guò)實(shí)例代碼補(bǔ)充介紹了Java 獲取兩個(gè)時(shí)間的時(shí)間差(時(shí)、分、秒)問(wèn)題,感興趣的朋友跟隨小編一起看看吧2024-03-03

