Java设计模式(一)——观察者模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ezview_uniview/article/details/65940111

        学习设计模式是IT人员必经之路,在实际工程中,如何对业务和逻辑的分离,对业务模式的理解是否深刻,如果只是简单的知道功能实现,我想无论工作几年,其实实际经验只是工作之初的1年,毫无长进,希望自己能够坚持把23种java设计模式全部撸一遍,夯实自己JAVA基础,这是对一个Android开发人员最基本的要求。

        观察者模式,又称订阅者模式,有主题对象,有订阅者对象,一个主题可以有多个订阅者。在实际工程应用中,什么样的场景需要用到观察者的设计模式?比如说,天气预报,设备采集到各种数据,如温度、湿度、PM2.5浓度等等,天气预报信息就相当于一个抽象的主体对象,具体的温湿度信息就是这个抽象主题的继承者,对于天气信息这种抽象信息,由一个抽象的订阅者订阅,具体的订阅者可以继承这个订阅了天气信息主题的订阅者,因此,具体的订阅者可以针对性的拿到具体的天气信息。

        这个场景可能说的有点啰嗦,现在来拿具体的例子来说明这个观察者模式的几个要素:

1、抽象主题

       抽象主题是一个接口,把所有观察者保存到集合中,一般是ArrayList,其中定义了三个方法,添加观察者、移除观察者、通知观察者更新。

2、具体主题

       具体主题继承抽象主题,内部主题发生改变时,通知订阅者更新状态。

3、抽象订阅者

      为所有主题订阅者提供接口,得到主题通知时更新自己

4、具体订阅者

       实现抽象主题的所有方法,保持自己状态和订阅的主题相协调

      如下图,观察者类图:

首先定义抽象主题,其中关于观察者主动拉取还是主题推送网络上有相关博文,感兴趣的朋友可以自己搜索,主要是Notify传递参数的使用技巧

public interface Subject {
    void registerListener(Observer observer);
    void removeListener(Observer observer);
    //观察者拉取
    void notifyChanged();

    //主题主动推送信息
    void notifyChanged(String t, String w, String p);
}

再定义具体的主题,看到观察者主动拉取是传递参数是主题本身,为的是获取到主题中的具体数据信息,而主题推送是观察者获得到信息后,直接更新自己

public class TemperatureSubject implements Subject {

    private static List<Observer> list = new ArrayList<>();
    private int data_t = 0;
    private int data_w = 0;
    private int data_p = 0;

    public int[] getData() {
        int[] array = {data_t, data_w, data_p};
        return array;
    }

    private void setData() {
        data_t = 5;
        data_w = 10;
        data_p = 15;
    }

    @Override
    public void registerListener(Observer observer) {
        if (observer != null) {
            if (!list.contains(observer)) {
                list.add(observer);
            }
        }
    }

    @Override
    public void removeListener(Observer observer) {
        if (list != null && list.size() > 0) {
            list.remove(observer);
        }
    }

    @Override
    public void notifyChanged() {
        setData();
        for (Observer o : list) {
            o.update(this);
        }
    }

    @Override
    public void notifyChanged(String t, String w, String p) {
        for (Observer o : list) {
            o.update(t, w, p);
        }
    }
}
再定义抽象观察者

public interface Observer {
    void update(Subject subject);
    void update(String t, String w, String p);
}
最后定义具体观察者,注意这里的callback是我自己定义的监听接口,因为在Android中获得到数据要回传到UI界面,所以回调了接口,实际中,也可以通过传入handler来处理,可以灵活运用

public class MyObserver implements Observer {

    private Subject subject;
    private CallBack callBack;

    public MyObserver(CallBack callBack) {
        this.callBack = callBack;
    }

    public MyObserver(CallBack callBack, Subject subject) {
        this.callBack = callBack;
        this.subject = subject;
    }


    @Override
    public void update(Subject subject) {
        int[] array = ((TemperatureSubject) subject).getData();
        callBack.update(String.valueOf(array[0]), String.valueOf(array[1]), String.valueOf(array[2]));

    }

    @Override
    public void update(String t, String w, String p) {
        callBack.update(t, w, p);
    }
}

最后来看一下Android客户端的调用:

public class MainActivity extends AppCompatActivity implements View.OnClickListener, CallBack{

    private Button mUp_tn;
    private MyObserver myObserver;
    private TemperatureSubject temperatureSubject;
    private TextView textView_t;
    private TextView textView_w;
    private TextView textView_p;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mUp_tn = (Button) findViewById(R.id.button);
        mUp_tn.setOnClickListener(this);
        textView_t = (TextView) findViewById(R.id.textView7);
        textView_w = (TextView) findViewById(R.id.textView);
        textView_p = (TextView) findViewById(R.id.textView2);
        temperatureSubject = new TemperatureSubject();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                //可以写监听callback,也可以写handler
                myObserver = new MyObserver(this);
                temperatureSubject.registerListener(myObserver);
                temperatureSubject.notifyChanged("39", "5", "60");
                break;
            case R.id.button2:
                if (myObserver != null) {
                    temperatureSubject.registerListener(myObserver);
                    temperatureSubject.notifyChanged();
                }
                break;
        }
    }

    @Override
    public void update(String t, String w, String p) {
        textView_t.setText(t + "°C");
        textView_w.setText(w + "级");
        textView_p.setText(p);
    }
}

客户端代码只是简单的调用,写法可能不是很规范,这些不是关注的重点,主要是学习观察者模式的思想,是一种消息订阅式的思想在里面,个人理解主要是在复杂逻辑里面的解耦会有很大帮助,值得深入研究。另外就是如果App涉及到控制设备,是不是可以考虑这种设计模式?尤其是在不同设备来回切换,哪个设备被订阅,哪个设备被解除订阅,可以随着UI层的动作,进行业务的切换。


猜你喜欢

转载自blog.csdn.net/ezview_uniview/article/details/65940111