觀察者模式2種用法---結合代理模式實現
在安卓的內容提供者ContentProvider,RxJava都運用到了觀察者模式
今天來了解並學習下觀察者模式,希望在自己編寫程式碼時候,更多的運用此模式
什麼是觀察者模式呢?
我是這樣理解觀察者模式的,當我去使用一個設計模式時候,我很喜歡將抽象的問題具體化
1、被觀察者
2、被觀察者的行為
3、觀察者
4、觀察者的行為
5、關聯2者的類(簡單的可以在被觀察者裡面去關聯2者)
首先先來了解一個最簡單的觀察者模式,我就拿一個最經典的例子來解釋
我和小明(觀察者)去訂報(觀察者行為),郵局(被觀察者)有報紙(被觀察者行為)就會通知我和小明
那麼首先來看觀察者的方法吧,觀察者裡面只有一個介面,就是郵件給我報紙,我就有報紙了,只有這一個方法
ObserverInterface
package com.godinsec;
//訂閱者
public interface ObserverInterface {
// 有新的報紙了就會被執行通知
void HasNewPaper();
}
再看來下觀察者類的具體實現吧,也就是我和小明,對外提供了一個setP_name和 getP_name的方法
ObserverImpl
package com.godinsec;
public class ObserverImpl implements ObserverInterface {
// 訂閱者的名字
private String p_name;
public ObserverImpl(String f_name) {
p_name = f_name;
}
public String getP_name() {
return p_name;
}
public void setP_name(String p_name) {
this.p_name = p_name;
}
// 告訴訂閱者有新報紙了
public void HasNewPaper() {
System.out.println(p_name + "!! 有新的報紙了,請查收!" );
}
}
然後就該涉及到被觀察者方法介面這塊了,也就是郵局實體類的方法,其實郵局最好只有傳送報紙的介面實現,哪些新增取消訂閱者,最好抽取出來一個新的類,我們就先看看被觀察者擁有訂閱取消的功能吧
它裡面只有新增和訂閱,以及自己的方法,那就是傳送報紙的功能
ObserveredInterface
package com.godinsec;
public interface ObserveredInterface
{
//新增訂閱者
void RegisterSubscriber(ObserverInterface f_subScribe);
//取消訂閱
void RemoveSubScriber(ObserverInterface f_subScribe);
//傳送報紙
void SendPaper();
}
繼續看下被觀察者,也就是我和小明的實體類
ObserveredImpl
package com.godinsec;
import java.util.ArrayList;
import java.util.List;
//人民日報
public class ObserveredImpl implements ObserveredInterface {
private List<ObserverInterface> subList = new ArrayList<ObserverInterface>();
public void RegisterSubscriber(ObserverInterface f_subScribe) {
subList.add(f_subScribe);
}
public void RemoveSubScriber(ObserverInterface f_subScribe) {
if (subList.indexOf(f_subScribe) >= 0) {
subList.remove(f_subScribe);
}
}
@Override
public void SendPaper() {
for (int i = 0; i < subList.size(); i++) {
ObserverImpl observerImpl = (ObserverImpl) subList.get(i);
System.out.println("----發報紙----"+observerImpl.getP_name());
subList.get(i).HasNewPaper();
}
}
}
通過新增訂閱的方式,然後在呼叫自己的方法SendPaper,去為每一個訂閱者傳送郵報,呵呵,這跟代理模式灰常像呀,如果你想了解代理模式,請戳如下連結:
最後看下測試類是如何實現的吧:
MyMainDemo
package com.godinsec;
public class MyMainDemo {
public static void main(String[] args) {
ObserveredImpl _paper = new ObserveredImpl();
ObserverImpl _me = new ObserverImpl("我");
ObserverImpl _XiaoMing = new ObserverImpl("小明");
// 小明訂報
_paper.RegisterSubscriber(_XiaoMing);
// 趙雲訂報
// 劉備訂報
_paper.RegisterSubscriber(_me);
// 有新報紙了
_paper.SendPaper();
System.out.println("---------------發完報紙了------------------");
// 小明不想訂了,取消報紙
_paper.RemoveSubScriber(_XiaoMing);
// 又有新報紙了 就沒有小明的報紙 了
_paper.SendPaper();
}
}
看下日誌輸出:
----發報紙----小明
小明!! 有新的報紙了,請查收!
----發報紙----我
我!! 有新的報紙了,請查收!
---------------發完報紙了------------------
----發報紙----我
我!! 有新的報紙了,請查收!
我們來改進改進上面那個觀察者模式
以上就是一個灰常簡單的觀察者模式,那麼我們接下來進行改造,郵局只有傳送郵報的方法,讓訂閱取消訂閱方法抽取出來
觀察者及其觀察者的方法沒有做更改還是如下的程式碼:
ObserverInterface
package com.godinsec;
//訂閱者
public interface ObserverInterface {
// 有新的報紙了就會被執行通知
void HasNewPaper();
}
ObserverImpl
package com.godinsec;
public class ObserverImpl implements ObserverInterface {
// 訂閱者的名字
private String p_name;
public ObserverImpl(String f_name) {
p_name = f_name;
}
public String getP_name() {
return p_name;
}
public void setP_name(String p_name) {
this.p_name = p_name;
}
// 告訴訂閱者有新報紙了
public void HasNewPaper() {
System.out.println(p_name + "!! 有新的報紙了,請查收!");
}
}
接下來看被觀察者類,及其介面方法,這個做了更改,只有傳送郵報的功能,取消了,訂閱和取消訂閱的功能,程式碼如下:
ObserveredInterface
package com.godinsec;
import java.util.List;
public interface ObserveredInterface {
// 傳送報紙
void SendPaper(List<ObserverInterface> subList);
}
ObserveredImpl
package com.godinsec;
import java.util.ArrayList;
import java.util.List;
//人民日報
public class ObserveredImpl implements ObserveredInterface {
@Override
public void SendPaper(List<ObserverInterface> subList) {
for (int i = 0; i < subList.size(); i++) {
ObserverImpl observerImpl = (ObserverImpl) subList.get(i);
System.out.println("----發報紙----"+observerImpl.getP_name());
subList.get(i).HasNewPaper();
}
}
}
最後我們新添加了一個控制類,就是將訂閱,取消訂閱摘出來了
ControllerInterface
package com.godinsec;
import java.util.List;
public interface ControllerInterface {
//新增訂閱者
void RegisterSubscriber(ObserverInterface f_subScribe);
//取消訂閱
void RemoveSubScriber(ObserverInterface f_subScribe);
//傳送報紙
void SendPaper();
}
ControllerImpl
package com.godinsec;
import java.util.ArrayList;
import java.util.List;
public class ControllerImpl implements ControllerInterface{
private List<ObserverInterface> subList = new ArrayList<ObserverInterface>();
ObserveredImpl observeredImpl;
@Override
public void RegisterSubscriber(ObserverInterface f_subScribe) {
subList.add(f_subScribe);
}
@Override
public void RemoveSubScriber(ObserverInterface f_subScribe) {
if (subList.indexOf(f_subScribe) >= 0) {
subList.remove(f_subScribe);
}
}
public ControllerImpl(ObserveredImpl observeredImpl) {
super();
this.observeredImpl = observeredImpl;
}
@Override
public void SendPaper() {
observeredImpl.SendPaper(subList);
}
}
最後來看下主介面程式碼把
MyMainDemo
package com.godinsec;
public class MyMainDemo {
public static void main(String[] args) {
ObserverImpl _me = new ObserverImpl("我");
ObserverImpl _XiaoMing = new ObserverImpl("小明");
ObserveredImpl _paper = new ObserveredImpl();
ControllerInterface controllerImpl = new ControllerImpl(_paper);
controllerImpl.RegisterSubscriber(_me);
controllerImpl.RegisterSubscriber(_XiaoMing);
// 有新報紙了
controllerImpl.SendPaper();
System.out.println("---------------發完報紙了------------------");
// 小明不想訂了,取消報紙
controllerImpl.RemoveSubScriber(_XiaoMing);
// 又有新報紙了 就沒有小明的報紙 了
controllerImpl.SendPaper();
}
}
log輸出如下:
----發報紙----我
我!! 有新的報紙了,請查收!
----發報紙----小明
小明!! 有新的報紙了,請查收!
---------------發完報紙了------------------
----發報紙----我
我!! 有新的報紙了,請查收!