如下圖,產品經理接到老闆通知,需要臨時新增需求,萬能的產品經理,立刻通知所有程序員去實現該需求。
小安用程序的形式實現上圖的過程,代碼如下:
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 老闆
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Boss {
public void sendOrder(){
ProductManager productManager = new ProductManager();
productManager.demandChanged();
}
}
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 產品經理
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class ProductManager {
public void demandChanged(){
Programmer programmer1 = new Programmer();
Programmer programmer2 = new Programmer();
Programmer programmer3 = new Programmer();
programmer1.updateCode();
programmer2.updateCode();
programmer3.updateCode();
}
}
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 程序員
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Programmer {
public void updateCode(){
//苦逼的完成需求
}
}
觀察者模式:
定義了對象之間的一對多依賴,這樣一來,當一個對象改變狀態時,它的所有依賴着都會受到通知並自動更新。
官方定義不太好理解,我翻譯一下,在觀察者模式中,對象之間有一對多的依賴關係,比如一個產品經理對多個程序員,當產品經理有需求變更時,他的所有依賴的程序員都會收到需求變更通知,並修改自己的程序完成該需求。
採用觀察者模式的UML圖:
繼承Subject的類:就是觀察者模式中的“被觀察者”,它會把所有觀察者保存在一個集合中。
實現Observer的類:就是觀察者模式中的“觀察者”,它會把自己註冊進被觀察者中的集合中,從而使被觀察者發生改變時,通知自己;也可以把自己從被觀察者集合中刪除,從而不接受觀察者發來的通知。
被觀察者父類:
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 抽象者父類
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Subject {
//觀察者對象列表
private List<Observer> observers = new ArrayList<Observer>();
/**
* 註冊觀察者對象
* @param observer
*/
public void registerObserver(Observer observer){
if(!observers.contains(observer)) {
observers.add(observer);
}
}
/**
* 解綁觀察者對象
*/
public void unRegisterObserver(Observer observer){
if(!observers.contains(observer)) {
observers.remove(observer);
}
}
//通知所有註冊的觀察者執行對應操作
public void notifyObservers(){
for (Observer observer : observers) {
observer.updateCode();
}
}
}
具體的被觀察者:
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 具體的被觀察者(產品經理)
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class ProductManager extends Subject{
private static class ProductManagerSingletonHolder {
private static final ProductManager INSTANCE = new ProductManager();
}
private ProductManager (){}
public static final ProductManager getInstance() {
return ProductManagerSingletonHolder.INSTANCE;
}
//需求變更,通知觀察者
public void demandChanged(){
notifyObservers();
}
}
觀察者公共接口:
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 抽象的觀察者,所有的觀察者都實現該接口
* 當被觀察者有變化需要通知時,有了一個共同的接口。
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public interface Observer {
void updateCode();
}
具體觀察者對象:
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 觀察者(程序員1)
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Programmer1 implements Observer{
public Programmer1() {
ProductManager.getInstance().registerObserver(this);
}
@Override
public void updateCode() {
//苦逼的完成需求
}
}
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 觀察者(程序員2)
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Programmer2 implements Observer{
public Programmer2() {
ProductManager.getInstance().registerObserver(this);
}
@Override
public void updateCode() {
//苦逼的完成需求
}
}
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 觀察者(程序員3)
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Programmer3 implements Observer{
public Programmer3() {
ProductManager.getInstance().registerObserver(this);
}
@Override
public void updateCode() {
//苦逼的完成需求
}
}
觸發條件:
/**
* @Author: 歡迎關注公衆號:程序員小安
* @description: 觸發條件:老闆
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Boss {
public void sendOrder(){
ProductManager.getInstance().demandChanged();
}
}
採用觀察者模式後,觀察者跟被觀察者之間完全松耦合,當需要新增一個新的觀察者時,因爲被觀察者唯一依賴的是一個實現Observer接口的列表,所以我們可以不修改原有被觀察者的代碼,隨時增加觀察者。同理,也可以隨時刪除某個觀察者。
另一方面,主要註冊的觀察者,一定會收到通知,不存在通知遺漏的情況。
觀察者模式的優點:
(1)具體被觀察者和具體觀察者是松耦合關係。
(2)觀察者模式滿足“開-閉原則”。
觀察者模式的缺點:
(1)如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
(2)如果在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能導致系統崩潰。
(3)觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。
觀察者模式的應用場景:
(1) 對一個對象狀態的更新,需要其他對象同步更新,而且其他對象的數量動態可變。
(2)對象僅需要將自己的更新通知給其他對象而不需要知道其他對象的細節。
如有錯誤歡迎指出來,一起學習。