1.什么是观察者模式?
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
2.怎么设计一个观察者模式的程序?
确定两个对象:主题和观察者
3.确定这两个对象之间的关系:
主题对象管理某些数据,一旦数据发生改变,会主动向观察者进行通知,然而观察者不必向主题进行索取。
主题并不知道具体的观察者是谁,这是它们之间的关系。
以上涉及到的设计原则:
为了交互对象之间的松耦合设计而努力
开始一个小例子
Observer接口:
- public interface ISubscribe {
- void getNewPaper();
- }
实现Observer接口的观察者:
个人订阅者:
- public class PersonalSubscriber implements ISubscribe {
- private String strName;
- public void setNewsPaperName(String strName){
- this.strName = strName;
- }
- public String getNewsPaperName(){
- return strName;
- }
- @Override
- public void getNewPaper() {
- // TODO Auto-generated method stub
- System.out.println("我是个人用户,我得到了我的报纸:"+getNewsPaperName());
- }
- }
企业订阅者:
- public class EnterpriseSubscriber implements ISubscribe {
- private String strName;
- public void setNewsPaperName(String strName){
- this.strName = strName;
- }
- public String getNewsPaperName(){
- return strName;
- }
- @Override
- public void getNewPaper() {
- // TODO Auto-generated method stub
- System.out.println("我是企业用户,我得到了我的报纸:"+getNewsPaperName());
- }
- }
被观察者:Subject
- public abstract class Publish {
- public List<ISubscribe> list;
- public Publish(){
- list = new ArrayList();
- }
- public void registered(ISubscribe iSubscribe){
- list.add(iSubscribe);
- }
- public void unregistered(ISubscribe iSubscribe){
- list.remove(iSubscribe);
- }
- public abstract void sendNewsPaper();
- }
这里使用的是抽象类
下面是实现:
- public class PostOffice extends Publish{
- @Override
- public void sendNewsPaper() {
- // TODO Auto-generated method stub
- Iterator iterator = list.iterator();
- while(iterator.hasNext()){
- ((ISubscribe) iterator.next()).getNewPaper();
- }
- }
- }
测试:
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- PostOffice postOffice = new PostOffice();
- //得到个人用户
- PersonalSubscriber person = new PersonalSubscriber();
- person.setNewsPaperName("《南方周末》");
- //得到企业用户
- EnterpriseSubscriber enterprise = new EnterpriseSubscriber();
- enterprise.setNewsPaperName("《企业报》");
- //注册观察者
- postOffice.registered(person);
- postOffice.registered(enterprise);
- //发放报纸
- postOffice.sendNewsPaper();
- }
测试结果:
- 我是个人用户,我得到了我的报纸:《南方周末》
- 我是企业用户,我得到了我的报纸:《企业报》
在Android中,button.setOnclickListener()这个方式是比较常见的观察者模式:当然,众所周知,onClick是著名的回调方法,在这里不会研究回调,不用太在意。
看下代码:
- Button button1 = (Button)findViewById(R.id.button1);
- Button button2 = (Button)findViewById(R.id.button2);
- Button button3 = (Button)findViewById(R.id.button3);
- button1.setOnClickListener(this);
- button2.setOnClickListener(this);
- button3.setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- switch(v.getId()) {
- case R.id.button1 :
- // do some thing
- case R.id.button2 :
- // do some thing
- case R.id.button3 :
- // do some thing
- }
- }
先button.setOnclickListener()进行注册。相当于邮局中的postOffice.registered(person)。onclick响应事件相当于邮局中的
- public void sendNewsPaper() {
- for(ISubscribe subscribe : SubscribeList) {
- subscribe.getNewsPaper();
- }
- }
这个中的subscribe.getNewsPaper()这个方法。View.onClickListener相当于邮局。View也就是button是我们的订阅者,也就相当于张三。我们也可以在getNewsPaper中加一些自己的switch判断。
最后,如果我们的邮局要实现类似button这样的回调这么实现呢?
- ISubscribe isubscribe;
- @Override
- public void getNewsPaper() {
- // TODO Auto-generated method stub
- System.out.println("我是"+getName()+",我收到我订阅的"+getNewsPaperName());
- isubscribe.getNewsPaper();
- }