設(shè)計模式——觀察者模式
觀察者模式又稱之為發(fā)布-訂閱模式:定義對象間一種一對多的依賴關(guān)系,使得每當(dāng)一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并且被自動的更新。
在日常生活中我們也會碰到許多的觀察者模式的例子。例如微信的訂閱推送、聽收音機、看直播、電腦中的文件系統(tǒng)。所以根據(jù)這些實際例子我們不難推導(dǎo)出其實在觀察者模式中,我們可以分為觀察者和被觀察者兩個角色。用類圖表示如下
觀察者模式類圖
-
Subject: 抽象的被觀察者。 -
Observer: 抽象的觀察者。 -
ConcreteSubject: 具體的被觀察者。 -
ConcreteObserver: 具體的觀察者。
電腦中的文件系統(tǒng)就是典型的觀察者模式,當(dāng)在一個目錄下新建一個文件時,此時這個動作就會通知目錄管理系統(tǒng)將此文件加入其中、另外磁盤管理系統(tǒng)也會相應(yīng)的減少內(nèi)存。在此情境中目錄就是一個被觀察者,而目錄管理系統(tǒng)和磁盤管理系統(tǒng)就是觀察者。
此時新建一個被觀察者的抽象類
abstract interface Subject{
List<Observer> observerList = new ArrayList<>();
public void attach(Observer observer);
public void detach(Observer observer);
public void myNotify(File file);
}
觀察者的抽象類
interface Observer{
public void update(File file);
}
目錄被觀察者
class ConcreteSubject implements Subject{
public void attach(Observer observer){
observerList.add(observer);
}
public void detach(Observer observer){
observerList.remove(observer);
}
public void addFile(File file){
observerList.forEach(observer -> {
observer.update(file);
});
}
}
磁盤管理系統(tǒng)觀察
class DiskObserve implements Observer{
private Integer DISK_SIZE = 1024;
@Override
public void update(File file) {
Integer fileSize = file.getSize();
setDISK_SIZE(getDISK_SIZE()-fileSize);
}
public Integer getDISK_SIZE() {
return DISK_SIZE;
}
public void setDISK_SIZE(Integer DISK_SIZE) {
this.DISK_SIZE = DISK_SIZE;
}
}
目錄管理系統(tǒng)觀察
class CatalogObserve implements Observer{
private List<String> fileNames = new ArrayList<>();
@Override
public void update(File file) {
fileNames.add(file.getName());
}
public String getFileName(){
StringBuffer stringBuffer = new StringBuffer();
fileNames.forEach(fileName->{
stringBuffer.append(fileName+",");
});
return stringBuffer.toString();
}
}
File類描述
class File{
private String name;
private Integer size;
}
一個簡單的文件管理系統(tǒng)就出現(xiàn)了,此時在此目錄中新建文件都會在相應(yīng)的目錄管理系統(tǒng)和磁盤管理系統(tǒng)進行相應(yīng)的更新操作。
Subject Buxuewushu = new ConcreteSubject();
Observer disk = new DiskObserve();
Observer cataLog = new CatalogObserve();
Buxuewushu.attach(disk);
Buxuewushu.attach(cataLog);
Buxuewushu.addFile(new File("q",100));
Buxuewushu.addFile(new File("x",100));
Buxuewushu.addFile(new File("y",100));
System.out.println(((DiskObserve) disk).getDISK_SIZE());
System.out.println(((CatalogObserve) cataLog).getFileName());
輸出如下
磁盤大小還有: 724
Buxuewushu目錄中文件有: q,x,y,