java 設計模式:觀察者

1、概念

在對象之間定義了一對多的依賴,使得麼當一個對象狀態發生改變,其相關依賴對象會收到通知並自動更新。

2、場景

  1. 一個抽象模型有兩個方面,其中一個方面依賴於另一個方面
  2. 一個對象的改變將導致一個或多個其他對象也發生改變
  3. 需要在系統中創建一個觸發鏈

3、UML結構圖分析

  • 抽象被觀察者角色:也就是一個抽象主題,它把所有對觀察者對象的引用保存在一個集合中,每個主題都可以有任意數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者角色。一般用一個抽象類和接口來實現。
  • 抽象觀察者角色:爲所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
  • 具體被觀察者角色:也就是一個具體的主題,在集體主題的內部狀態改變時,所有登記過的觀察者發出通知。
  • 具體觀察者角色:實現抽象觀察者角色所需要的更新接口,一邊使本身的狀態與製圖的狀態相協調。

4、實際代碼分析

實現觀察者代碼:


/**
 *
 * 創建觀察者抽象類
 */
public interface Observer {

//更新方法
    void update(String newStatus);

}

/**
 * 創建觀察者實現類
 */
public class ConcreteObserver implements Observer {

    /**
     * 觀察者狀態
     */
    private String observerState;

    @Override
    public void update(String newStatus) {
        observerState = newStatus;
        System.out.println(newStatus);
    }
}

/**
 * 創建抽象目標者
 * Created by shidawei on 2019/5/23.
 */
public abstract class Subject {

    private List<Observer> mObservers = new ArrayList<>();

    /**
     * 註冊觀察
     * @param observer
     */
    public void attach(Observer observer){
        mObservers.add(observer);
        System.out.println("註冊觀察");
    }

    /**
     * 移除觀察者
     * @param observer
     */
    public void detach(Observer observer){
        mObservers.remove(observer);
    }

    /**
     * 通知觀察者
     * @param newStatus
     */
    public void notifyObsercers(String newStatus){
        for(Observer observer:mObservers){
            observer.update(newStatus);
        }
    }
}

/**
 * 實現被觀察者
 */
public class ConcreteSubject extends Subject {
    private String state;

    public String getState() {
        return state;
    }
    public void change(String newState){
        state = newState;
        System.out.println(newState);
        notifyObsercers(newState);
    }
}

//測試代碼
ConcreteSubject concreteSubject = new ConcreteSubject();
        concreteSubject.attach(new ConcreteObsercer());
        concreteSubject.attach(new ConcreteObsercer());
        concreteSubject.attach(new ConcreteObsercer());
        concreteSubject.change("123");

java內部的接口實現:

/**
 * Observable 是被觀察者對象接口,是對被觀察者的實現
 */
public class TargetObervable extends Observable {

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
        //被觀察者數據發生改變的時候通過如下兩行代碼通知所有觀察者
        this.setChanged();
        this.notifyObservers();
    }
}
/**
 * Observer 對象是觀察者,實現Observer的對象就是實現觀察者對象
 */
public class TargetOberver implements Observer {


    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println(name + "收到數據變更" + ((TargetObervable) o).getMessage());
    }
}

//測試代碼

        TargetObervable targetObervable = new TargetObervable();
        targetObervable.addObserver(new TargetOberver());
        targetObervable.addObserver(new TargetOberver());
        targetObervable.addObserver(new TargetOberver());
        targetObervable.setMessage("1234");

兩種觀察者對比:

通過讀源碼Observable.class我們得知對Observer的集合爲Vector

Vector爲線程安全的,會保證線程安全,但是性能差。可以採用CopyOnWriteArrayList來代替Vector。

觀察者設計模式在Android中的實際運用

回調模式:一對一的模式

實現了抽象類/接口的實例實現了負累的提供的抽象方法,然後將該方法還給父類來處理。

Fragment與activity通信的代碼實例:

/**
*回調接口,與activity通信
**/

public interface ISwitchCaoZuoRecordFragment {
        void toSwitch(CaiZuoRecordFragFragment fragment, CaiZuoRecordFragPresenter presenterDecorator);
    }
/**
* activity實現該接口
**/
public class CaoZuoRecordActivity extends BaseActivity<CaoZuoRecordView, CaoZuoRecordPresenter> implements CaoZuoRecordView ,CaiZuoRecordFragFragment.ISwitchCaoZuoRecordFragment{
    @Override
    public void toSwitch(CaiZuoRecordFragFragment fragment, CaiZuoRecordFragPresenter presenterDecorator) {
        mPresenterDecorator = presenterDecorator;
        if(presenterDecorator.studentName!=null&&!presenterDecorator.studentName.equals("")){
            searchListTitleBar.getSearch().setText(presenterDecorator.studentName);
            searchListTitleBar.getClear().setVisibility(View.VISIBLE);
            searchListTitleBar.getSearch_layout().setVisibility(View.VISIBLE);
        }else{
            searchListTitleBar.getSearch().setText("");
            searchListTitleBar.getClear().setVisibility(View.GONE);
            searchListTitleBar.getSearch_layout().setVisibility(View.GONE);
        }

    }

/**
*fragment註冊和取消
*/
    @Override
    public void onDetach() {
        super.onDetach();
        iSwitchCaoZuoRecordFragment = null;

    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof ISwitchCaoZuoRecordFragment) {
            iSwitchCaoZuoRecordFragment = (ISwitchCaoZuoRecordFragment) context;
        }else{
            throw new RuntimeException(context.toString()
                    + " 必須實現 ISwitchCaoZuoRecordFragment");
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章