設計模式之觀察者模式(例項+Demo)
你能從本文了解到如下幾個方面:1. 什麼是觀察者模式?2. 如何使用觀察者模式。 3. Java中的觀察者模式的使用。 4. 總結。5. 原始碼
1. 什麼是觀察者模式?
觀察者模式又被稱為釋出訂閱模式。它定義了物件之間一對多的依賴,當一個物件狀態發生改變時,它的所有依賴者都會收到通知並自動更新相關內容。我們可以拿報社來舉例:一家報社(Subject)一發布報紙,就會立馬派送給所有訂報(Obsever)的人,訂報的人就能獲取報紙內容。當然我們的觀察者模式比報社的及時性更高。
2. 如何使用觀察者模式?
就上面的問題,我們現在來做這樣一個需求:將報社釋出的新報紙派送到所有訂閱者的手裡。
思路:
1. 首先我們建立一個主題類介面:ISubject,所有被觀察者都可以繼承這個介面(這裡指報社)
2. 我們建立一個報社類(NewsPaperOffice),實現主題類介面(ISubject)
3. 我們給所有的訂閱者建立一個收到訊息的介面(IObserver)
4. 所有的訂閱者實現這個介面。
程式碼實現:
public interface ISubject {//主題介面
void registerObserver(IObserver iObserver);
void removeObserver(IObserver iObserver);
void notifyObserver();
}
public class NewsPaperOffice implements ISubject {//報社(主題)
private int time = 1;
private List<IObserver> mList = new ArrayList<>();
@Override
public void registerObserver(IObserver iObserver) {
if (iObserver != null) {
mList.add(iObserver);
}
}
@Override
public void removeObserver(IObserver iObserver) {
mList.remove(iObserver);
}
@Override
public void notifyObserver() {
for (int i = 0; i < mList.size(); i++) {
mList.get(i).update("第"+time +"次發的新聞");
}
time ++ ;
}
}
public interface IObserver {//觀察者介面
void update(String s);
}
public class FirstObserver implements IObserver {//觀察者實現
private String message;
public String getMessage() {
return message;
}
@Override
public void update(String s) {
message = "FirstObserver 收到了" + s;
}
}
public class SecondObserver implements IObserver {//觀察者實現
private String message;
public String getMessage() {
return message;
}
@Override
public void update(String s) {
message = "SecondObserver 收到了" + s;
}
}
實現一個簡單的邏輯呼叫:
public class ObserverActivity extends AppCompatActivity {
@BindView(R.id.btn_send_broadcast)
Button mBtnSendBroadcast;
@BindView(R.id.first_observer_tv)
TextView mFirstObserverTv;
@BindView(R.id.first_observer_btn)
Button mFirstObserverBtn;
@BindView(R.id.second_observer_tv)
TextView mSecondObserverTv;
@BindView(R.id.sencond_observer_btn)
Button mSencondObserverBtn;
private NewsPaperOffice mNewsPaperOffice;
private FirstObserver mFirstObserver;
private SecondObserver mSecondObserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_obaser);
ButterKnife.bind(this);
}
@OnClick({R.id.btn_send_broadcast, R.id.first_observer_btn, R.id.sencond_observer_btn})
public void onViewClicked(View view) {
if (mNewsPaperOffice == null) {
mNewsPaperOffice = new NewsPaperOffice();
}
switch (view.getId()) {
case R.id.btn_send_broadcast:
mNewsPaperOffice.notifyObserver();
if (mFirstObserver != null) {
mFirstObserverTv.setText(mFirstObserver.getMessage());
}
if (mSecondObserver != null) {
mSecondObserverTv.setText(mSecondObserver.getMessage());
}
break;
case R.id.first_observer_btn:
if (mFirstObserver == null) {
mFirstObserver = new FirstObserver();
}
if(mFirstObserverBtn.getText().equals("訂閱報紙")){
mFirstObserverBtn.setText("取消訂閱");
mNewsPaperOffice.registerObserver(mFirstObserver);
}else{
mFirstObserverBtn.setText("訂閱報紙");
mNewsPaperOffice.removeObserver(mFirstObserver);
}
break;
case R.id.sencond_observer_btn:
if (mSecondObserver == null) {
mSecondObserver = new SecondObserver();
}
if(mSencondObserverBtn.getText().equals("訂閱報紙")){
mSencondObserverBtn.setText("取消訂閱");
mNewsPaperOffice.registerObserver(mSecondObserver);
}else{
mSencondObserverBtn.setText("訂閱報紙");
mNewsPaperOffice.removeObserver(mSecondObserver);
}
break;
}
}
}
至此我們已經實現了一個觀察者模式。
3.JAVA中的觀察者模式的使用
Java中的觀察者模式主題需要繼承java.util.Observable,觀察者需要實現java.util.Observer。通過notifyObservers()方法傳送通知,在呼叫此方法之前需要呼叫setChanged()修改傳送狀態。
主題類(NewsPaperOfficeJava):
public class NewsPaperOfficeJava extends Observable {
private String message;
private int time = 1;
public void sendMessage(){
message = "第"+time +"次發的新聞";
setChanged();
notifyObservers();
time++;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
觀察者的實現:
public class FirstObserverJava implements Observer {//JAVA觀察者實現
private String message;
Observable mObservable;
public String getMessage() {
return message;
}
@Override
public void update(Observable o, Object arg) {
mObservable = o;
if(mObservable instanceof NewsPaperOfficeJava){
message = "FirstObserver 收到了" + ((NewsPaperOfficeJava) mObservable).getMessage();
}
}
}
……
實現邏輯和第一種實現方式差不多,修改下型別和方法即可,不做贅述。
4. 總結
使用Java的觀察者模式的弊端: 前面有提到過,Java中的觀察者主題需要繼承java.util.Observable,這樣就會導致一個問題,如果說我們上面的NewsPaperOfficeJava需要具有另外一個超類的行為時,這時候就會比較麻煩,因為Java中咱們不能使用多繼承去實現。當然,如果我們自己能夠去擴充套件java.util.Observable,那麼還是可以去使用的,一般情況下推薦自己實現一套觀察者模式。