最近在学习下设计模式,而加深学习的不错的方法就是把心得写出来吧。记录下自己的理解。现在自己看的书是《head.Frist设计模式》这本书。比较不错,想学习设计模式的朋友可以看下这本书。


观察者<Observer>模式(有时又被称为发布-订阅<Publish/Subscribe>模式、模型-视图<Model/View>模式、源-收听者<Source/Listener>模式或从属者<Dependents>模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。(源自百度百科)

(五月三十一号修正内容)

看下结构图:


开始一个小例子

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;}@Overridepublic void getNewPaper() {// TODO Auto-generated method stubSystem.out.println("我是个人用户,我得到了我的报纸:"+getNewsPaperName());}}

企业订阅者:

public class EnterpriseSubscriber implements ISubscribe {    private String strName;public void setNewsPaperName(String strName){this.strName = strName;}public String getNewsPaperName(){return strName;}@Overridepublic void getNewPaper() {// TODO Auto-generated method stubSystem.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{@Overridepublic void sendNewsPaper() {// TODO Auto-generated method stubIterator iterator = list.iterator();while(iterator.hasNext()){((ISubscribe) iterator.next()).getNewPaper();}}}

测试:

public static void main(String[] args) {// TODO Auto-generated method stubPostOffice postOffice = new PostOffice();//得到个人用户PersonalSubscriber person = new PersonalSubscriber();person.setNewsPaperName("《南方周末》");//得到企业用户EnterpriseSubscriber enterprise = new EnterpriseSubscriber();enterprise.setNewsPaperName("《企业报》");//注册观察者postOffice.registered(person);postOffice.registered(enterprise);//发放报纸postOffice.sendNewsPaper();}

测试结果:

我是个人用户,我得到了我的报纸:《南方周末》我是企业用户,我得到了我的报纸:《企业报》



下面是有些错误五月18号版本:后面有错误解析!

举个例子,张三从邮局订阅了《南方周末》,李四从邮局订阅了《新京报》,王五从邮局里面订阅了《南方都市报》。当报纸抵达邮局的时候,邮局就会把报纸送递订阅者。而不需要订阅者天天到邮局询问报纸是否到达邮局。

下面开始代码:首先应该是个订阅者接口:

package cn.demo;public interface ISubscribe {//从邮局订阅报纸public void registered(PostOffice postOffice);//从邮局退订报纸public void unregistered(PostOffice postOffice);//获取报纸名称public void getNewsPaper();}

第三个方法非必须,前两个方法必须要有。(应修改为前两个非必须,第三个方法必须有)

然后有三个订阅者类:

张三:

package cn.demo;public class ZhangSan implements ISubscribe{private String mName;private String mNewsPaperName;public ZhangSan(String mName, String mNewsPaperName) {this.mName = mName;this.mNewsPaperName = mNewsPaperName;}public String getName() {return mName;}public String getNewsPaperName() {return mNewsPaperName;}@Overridepublic void registered(PostOffice postOffice){postOffice.registeredNewsPaper(this);}@Overridepublic void unregistered(PostOffice postOffice){postOffice.unregisteredNewsPaper(this);}@Overridepublic void getNewsPaper() {// TODO Auto-generated method stubSystem.out.println("我是"+getName()+",我收到我订阅的"+getNewsPaperName());}}

李四:

package cn.demo;public class Lisi implements ISubscribe{private String mName;private String mNewsPaperName;public Lisi(String mName, String mNewsPaperName) {this.mName = mName;this.mNewsPaperName = mNewsPaperName;}public String getName() {return mName;}public String getNewsPaperName() {return mNewsPaperName;}@Overridepublic void unregistered(PostOffice postOffice){postOffice.unregisteredNewsPaper(this);}@Overridepublic void registered(PostOffice postOffice){postOffice.registeredNewsPaper(this);}@Overridepublic void getNewsPaper() {// TODO Auto-generated method stubSystem.out.println("我是"+getName()+",我收到我订阅的"+getNewsPaperName());}}

王五:

package cn.demo;public class Wangwu implements ISubscribe{private String mName;private String mNewsPaperName;public Wangwu(String mName, String mNewsPaperName) {this.mName = mName;this.mNewsPaperName = mNewsPaperName;}public String getName() {return mName;}public String getNewsPaperName() {return mNewsPaperName;}@Overridepublic void registered(PostOffice postOffice){postOffice.registeredNewsPaper(this);}@Overridepublic void unregistered(PostOffice postOffice){postOffice.unregisteredNewsPaper(this);}@Overridepublic void getNewsPaper() {// TODO Auto-generated method stubSystem.out.println("我是"+getName()+",我收到我订阅的"+getNewsPaperName());}}

三个订阅者,都有方法订阅报纸,或者取消订阅。其实关于订阅者的信息,是存储在邮局类里面。


邮局类:(邮局类应该继承一个抽象类或者接口(Subject),这里没有实现)

import java.util.ArrayList;import java.util.List;public class PostOffice {private List<ISubscribe> SubscribeList = new ArrayList<ISubscribe>();public void registeredNewsPaper(ISubscribe subscribe) {SubscribeList.add(subscribe);}public void unregisteredNewsPaper(ISubscribe subscribe) {if (subscribe != null) {SubscribeList.remove(subscribe);}}public void getNewsPaper(boolean bool) {if (bool) {sendNewsPaper();}}public void sendNewsPaper() {for(ISubscribe subscribe : SubscribeList) {subscribe.getNewsPaper();}}}
在这个类里面,有变化通知是使用的sendNewsPaper()这个方法,遍历所有的订阅者。
测试类:

public static void main(String[] args) {// TODO Auto-generated method stubPostOffice mPostOffice = new PostOffice();ISubscribe zhangsan = new ZhangSan("张三", "《南方周末》");ISubscribe lisi = new Lisi("李四", "《新京报》");ISubscribe wangwu = new Wangwu("王五", "《南方都市报》");//开始订阅报纸zhangsan.registered(mPostOffice);lisi.registered(mPostOffice);wangwu.registered(mPostOffice);//邮局收到报纸,开始发放mPostOffice.getNewsPaper(true);//李四退订lisi.unregistered(mPostOffice);//邮局收到报纸,开始发放mPostOffice.getNewsPaper(true);}

打印结果:

我是张三,我收到我订阅的《南方周末》我是李四,我收到我订阅的《新京报》我是王五,我收到我订阅的《南方都市报》我是张三,我收到我订阅的《南方周末》我是王五,我收到我订阅的《南方都市报》

这里只是提供了一个简单的例子,而且代码你会发现有冗余,三个订阅者类,几乎是一样,因为没有在类里面添加他们独自的属性,可以用一个Person类来替代。这里写这三个类是为了显示清晰。

关于五月18号的例子,观察者没必要有注册和取消注册的方法。他们的方法的实现也是调用的被观察者的注册和取消注册,不如直接使用被观察者的方法。

在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);    }@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch(v.getId()) {case R.id.button1 ://do some thingcase R.id.button2 ://do some thingcase R.id.button3 ://do some thing}}

先button.setOnclickListener()进行注册。相当于邮局中的lisi.registered(mPostOffice),此处错误,应该是第一例中的postOffice.registered(person)。onclick响应事件相当于邮局中的

public void sendNewsPaper() {for(ISubscribe subscribe : SubscribeList) {subscribe.getNewsPaper();}}

这个中的subscribe.getNewsPaper()这个方法。View.onClickListener相当于邮局。View也就是button是我们的订阅者,也就相当于张三。我们也可以在getNewsPaper中加一些自己的switch判断。

最后,如果我们的邮局要实现类似button这样的回调这么实现呢?

ISubscribe isubscribe;@Overridepublic void getNewsPaper() {// TODO Auto-generated method stubSystem.out.println("我是"+getName()+",我收到我订阅的"+getNewsPaperName());isubscribe.getNewsPaper();}

在这里,弄的有点绕,其实可以另起一个接口。不知道是否能够明白,不明白欢迎留言探讨。谢谢,今天就到此,周末愉快!



更多相关文章

  1. 借助HorizontalScrollView实现多列ListView的横向滑动(含动态加
  2. android LiveData
  3. Android事件总线框架设计:EventBus3.0源码详解与架构分析(中)
  4. Android中的RxJava详解
  5. Android(安卓)websocket长连接+点对点订阅
  6. Android中的RecyclerView源码分析
  7. Android事件总线:EventBus
  8. SpringBoot webSocket 发送广播、点对点消息,Android接收
  9. Android(安卓)Google购买PHP服务器端验证(订阅购买和一次性购买)

随机推荐

  1. Gallery 画廊
  2. android开发 常用技巧
  3. 【译】Android(安卓)6.0接口变化(三)(Androi
  4. 【Android】Android(安卓)Studio中gradle
  5. 2013.12.23 (2)——— android 代码调用she
  6. Flutter1.12与原生Android交互(kotlin)
  7. android获取手机号码以及imsi信息
  8. android 源码导入到android studio
  9. Android(安卓)通过继承TextView类自定义
  10. android 系统属性 build.prop