设计模式之观察者模式(实例+Demo)

版权声明:本文为博主原创文章,转载请声明。 https://blog.csdn.net/qq_32175491/article/details/79548644

你能从本文了解到如下几个方面: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,那么还是可以去使用的,一般情况下推荐自己实现一套观察者模式。

5. 源码

Android设计模式系列源码地址如果对有用,希望能点个star.

猜你喜欢

转载自blog.csdn.net/qq_32175491/article/details/79548644
今日推荐