一個demo讓你徹底搞懂觀察者模式

介紹

觀察者模式也被稱爲發佈-訂閱(Publish/Subscribe)模式,它屬於行爲型模式的一種。觀察者模式定義了一種一對多的依賴關係,一個主題對象可被多個觀察者對象同時監聽。當這個主題對象狀態變化時,會通知所有觀察者對象並作出相應處理邏輯。

UML

觀察者模式UML

觀察者模式定義了四種角色:抽象主題、具體主題、抽象觀察者、具體觀察者。

  1. 抽象主題(Subject):該角色是一個抽象類或接口,定義了增加、刪除、通知觀察者對象的方法。
  2. 具體主題(ConcreteSubject):該角色繼承或實現了抽象主題,定義了一個集合存入註冊過的具體觀察者對象,在具體主題的內部狀態發生改變時,給所有註冊過的觀察者發送通知。
  3. 抽象觀察者(Observer):該角色是具體觀察者的抽象類,定義了一個更新方法。
  4. 具體觀察者(ConcrereObserver):該角色是具體的觀察者對象,在得到具體主題更改通知時更新自身的狀態。

實現代碼

抽象觀察者(Observer)接口

public interface Observer {

     public void update(String msg, TextView tv);
}

具體觀察者(Person)類

public class Person implements Observer {

    // 用戶名
    private String name;
    public Person(String name) {
        this.name = name;
    }

    @Override
    public void update(String msg, TextView tv) {
        tv.setText(tv.getText()+name+":"+ msg +"\n");
    }

}

抽象主題(Subject)接口

public interface Subject {
    /**
     * 增加觀察者
     * @param observer
     */
    public void attach(Observer observer);
    /**
     * 刪除觀察者
     * @param observer
     */
    public void detach(Observer observer);
    /**
     * 通知觀察者
     */
    public void notify(String message, TextView v);
}

具體主題(XiaosongSubject)類

public class XiaosongSubject implements Subject {

    //用於保存訂閱了小嵩的博客的用戶
    private List<Observer> mPersonList = new ArrayList<>();

    @Override
    public void attach(Observer observer) {
        mPersonList.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        mPersonList.remove(observer);
    }

    @Override
    public void notify(String message, TextView tv) {
        for (Observer observer : mPersonList) {
            observer.update(message,tv);
        }
    }
}

MainActivity類

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Person pMing,pQing,pLiang;
    private XiaosongSubject mSubject;

    private TextView tv_output;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initEvent();
    }

    private void initView() {

        findViewById(R.id.btn_add_one).setOnClickListener(this);
        findViewById(R.id.btn_add_two).setOnClickListener(this);
        findViewById(R.id.btn_add_three).setOnClickListener(this);

        findViewById(R.id.btn_notify).setOnClickListener(this);
        findViewById(R.id.btn_delete).setOnClickListener(this);

        tv_output = (TextView)findViewById(R.id.tv_output);
    }

    private void initEvent() {
        //創建被觀察者(具體主題)
        mSubject = new XiaosongSubject();
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_add_one://註冊觀察者 小明
                if (pMing==null){
                    pMing = new Person("小明");
                    mSubject.attach(pMing);
                    Toast.makeText(this,"小明關注了我",Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(this,"小明已關注我了,不能再重複操作",Toast.LENGTH_SHORT).show();
                }
                break;

            case R.id.btn_add_two://註冊觀察者 小琴
                if (pQing==null){
                    pQing = new Person("小琴");
                    mSubject.attach(pQing);
                    Toast.makeText(this,"小琴關注了我",Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(this,"小琴已關注我了,不能再重複操作",Toast.LENGTH_SHORT).show();
                }
                break;

            case R.id.btn_add_three://註冊觀察者 阿亮
                if (pLiang==null){
                    pLiang = new Person("阿亮");
                    mSubject.attach(pLiang);
                    Toast.makeText(this,"阿亮關注了我",Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(this,"阿亮已關注我了,不能再重複操作",Toast.LENGTH_SHORT).show();
                }
                break;

            case R.id.btn_notify://主題(被觀察者)更新了內容,通知所有觀察者
                tv_output.setText("");
                mSubject.notify("小嵩更新微博啦~ 快來看看吧", tv_output);
                break;

            case R.id.btn_delete://註銷觀察者 小明
                if (pMing!=null){
                    mSubject.detach(pMing);
                    pMing = null;
                }

                if (pQing!=null){//註銷觀察者 小琴
                    mSubject.detach(pQing);
                    pQing = null;
                }

                if (pLiang!=null){//註銷觀察者 阿亮
                    mSubject.detach(pLiang);
                    pLiang = null;
                }

                break;

            default:
                break;
        }
    }
}

總結

在Android中,有很多場景使用了觀察者模式,比如Android的源碼裏:OnClickListener、ContentObserver、android.database.Observable等;還有第三方開源庫EventBus、RxJava、RxAndroid等。具體可閱讀它們的源碼去理解和體會。這裏我寫了一個簡單的demo,以便對它有更加深刻的理解,覺得這篇文章有用的話,可以點個贊哦~

GitHub的示例項目鏈接地址:ObserverPatternDemo

這裏寫圖片描述

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