一:前言
最近在遇到了Android的开发中常用到的设计模式之观察者模式,观察者模式,所谓的模式就是一种设计思想,可以按照某种模式,写出更合理,简单,有效的代码。可以用在Android开发中,也可以用在Java,C#等等开发中,就类似单例模式,代理模式,模版等等。
二:什么是观察者模式
个人理解所谓的观察者模式,打个比喻,就好比,老师在教室上课,学生在教室听课,这里的老师就是被观察者,而这时候的在听课的学生就是观察者,老师通过说话,来传递知识,老师每说一个知识,学生都会实时做出相应的反映。这就是所谓的观察者模式,也有人理解为事件的订阅,再以事件的订阅打个比喻,假设现在有个Android授课老师在讲课,有想学习Android的学生想实时的学习到新的Android知识,那怎么办,没错那就是必须的关注这个老师,你才能实时的获取到最新的Android知识,这里的关注就是,关注的过程就是事件的订阅。(个人理解,有什么不的对的地方,欢迎指教)
三:举例说明
我们这里用实际的需求来说明下.
需求:现在有学生A(也就是Activity) 去回答老师提出的问题,最后有老师,告诉学生是否回答正确,如果回答正确的学生,开心的笑了,不正确学生表现很沮丧。(也就是跳转到B Activity,去回答问题,最后提交,服务器将答题结果发布,A Activity接收结果,根据结果做出一些操作)
四:具体代码实现
1.这里我们先定义一个被观察者,也就是老师类。
package com.zhang.zs.zhangtest; import java.util.Observable; /** * Created by zs on 2016/11/12. * 老师类,老师就是给自己的学生传播知识,让自己的学生收益。 * 这里老师就好像是一个消息的发送者,可以认为,老师就是被观察者 * 这里继承系统的Observable类 * name_ok.由于在同一时间段,只能有一个老师给学生传递知识,所以我们要把老师类(被观察者,事件发送源) * 对象设计成单例模式 */ public class Teacher extends Observable { private Teacher() { } private static Teacher teacher = null; public static Teacher getInstance() { if (teacher == null) { synchronized (Teacher.class) { if (teacher == null) { teacher = new Teacher(); } } } return teacher; } public void postMessage(String eventtype) { setChanged(); notifyObservers(eventtype); } }
这里Teacher类就是被观察者,设计成单例模式,就是为了让整个系统中只存在一个消息的发送者。
2.现在新建一个EventType类。这里定义了一些,老师具体发送了一些什么信息,
package com.zhang.zs.zhangtest; /** * Created by zs on 2016/11/12. * 定义一些事件常量 * */ public class EventType { public static final String RESPONSE_SUCESS="resposeok"; //回答正确 public static final String RESPONSE_FAIL="responseno"; //回答错误 }
3.老师发送消息,学生怎能接受的到呢,到底是那个学生接受到呢,就好比我是哈佛校长(校长也是老师)发布的内部消息,当然只有,哈佛学校的学生才能接受消息把,这里是有关联的,如果你想接受哈佛的消息怎么办,想办法加入哈佛呗,这里的观察者也是一样的。首先将我们的A Activity 注册到 我们的消息的发送者中。让他知道有你这个学生。在一般开发中我们都会定义一个基类,这里我们也定义一个基类,(观察者多的话,一个一个添加多麻烦)。基类如下
package com.zhang.zs.zhangtest; import android.app.Activity; import android.os.Bundle; import java.util.Observable; import java.util.Observer; /** * Created by zs on 2016/11/12. */ public class BaseActivity extends Activity implements Observer{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(this instanceof Observer){ //将要接收消息的学生添加 Teacher.getInstance().addObserver(this); } } //接受到消息的回调方法,就是学生接受到消息后做出的反映 @Override public void update(Observable observable, Object data) { } }
4.这时候我们来定义一个学生,(A activity)
功能:一个按钮,一个显示图片的控件,点击按钮,转到B activity ,图片控件,显示根据老师公布学生答题的对错的结果去显示相应的图片,
布局文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="reply" android:text="我要回答问题" /> <ImageView android:id="@+id/image" android:layout_width="80dp" android:layout_height="80dp" android:layout_centerInParent="true" /> </RelativeLayout>
Activity 代码;
package com.zhang.zs.zhangtest; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import java.util.Observable; public class MainActivity extends BaseActivity { private ImageView image; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); image = (ImageView) findViewById(R.id.image); } public void reply(View v) { //跳转也去答题 startActivity(new Intent(this, ReplayActivity.class)); } /** * 根据接收到的消息去做相关的功能 * @param observable * @param data */ @Override public void update(Observable observable, Object data) { if (data instanceof String) { String message = (String) data; // 接收到成功消息就显示成功的图片 ,失败就显示失败的图片 if (EventType.RESPONSE_SUCESS.equals(message)) { image.setBackgroundResource(R.drawable.name_ok); } else if (EventType.RESPONSE_FAIL.equals(message)) { image.setBackgroundResource(R.drawable.name_err); } } } }
5.这里定义答题activity,根据答题结果,老师(被观察者)发出相应的消息。
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="题目一:1+1=?" android:textSize="19sp" /> <RadioGroup android:id="@+id/anser" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal"> <RadioButton android:id="@+id/two" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="2" android:textSize="19sp" /> <RadioButton android:id="@+id/three" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="3" android:textSize="19sp" /> <RadioButton android:id="@+id/four" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="4" android:textSize="19sp" /> <RadioButton android:id="@+id/five" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="5" android:textSize="19sp" /> </RadioGroup> <Button android:layout_marginTop="20dp" android:text="提交" android:onClick="response" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
想用activity代码:
package com.zhang.zs.zhangtest; import android.os.Bundle; import android.view.View; import android.widget.RadioGroup; import android.widget.Toast; public class ReplayActivity extends BaseActivity { private RadioGroup anser; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_replay); anser = (RadioGroup) findViewById(R.id.anser); } //根据消息发送消息 public void response(View view) { int checkId = anser.getCheckedRadioButtonId(); if (checkId == R.id.two) { // 老师发送答题成功的消息 Teacher.getInstance().postMessage(EventType.RESPONSE_SUCESS); } else if (checkId == R.id.three || checkId == R.id.four || checkId == R.id.five) { // 老师发送答题失败的消息 Teacher.getInstance().postMessage(EventType.RESPONSE_FAIL); } else { Toast.makeText(this, "请回答这个问题", Toast.LENGTH_SHORT).show(); return; } finish(); } }
项目源码地址:github.com/sdsjk/Obser…
到现在,整个需求就做完了,在重复一下,点击mainActivity中的按钮去跳转到 Bactivity去答题,答完题,点击提交按钮,会根据你的答案发送出不同的消息,这时候,Mainactivity就会接受到消息,做出相应的处理。如图
以上就是我对观察者模式的理解,有什么不恰当的地方请指教。