学习设计模式是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层的动作,进行业务的切换。