浅学设计模式之观察者模式及在android中的应用

标签: 设计模式 观察者 模式 | 发表时间:2012-05-18 23:34 | 作者:aomandeshangxiao
出处:http://blog.csdn.net

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

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

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

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

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;
	}
	
	@Override
	public void registered(PostOffice postOffice){
		postOffice.registeredNewsPaper(this);
	}
	
	@Override
	public void unregistered(PostOffice postOffice){
		postOffice.unregisteredNewsPaper(this);
	}

	@Override
	public void getNewsPaper() {
		// TODO Auto-generated method stub
		System.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;
	}
	
	@Override
	public void unregistered(PostOffice postOffice){
		postOffice.unregisteredNewsPaper(this);
	}
	
	@Override
	public void registered(PostOffice postOffice){
		postOffice.registeredNewsPaper(this);
	}

	@Override
	public void getNewsPaper() {
		// TODO Auto-generated method stub
		System.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;
	}
	
	@Override
	public void registered(PostOffice postOffice){
		postOffice.registeredNewsPaper(this);
	}
	
	@Override
	public void unregistered(PostOffice postOffice){
		postOffice.unregisteredNewsPaper(this);
	}


	@Override
	public void getNewsPaper() {
		// TODO Auto-generated method stub
		System.out.println("我是"+getName()+",我收到我订阅的"+getNewsPaperName());
	}

}

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


邮局类:

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 stub
		PostOffice 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类来替代。这里写这三个类是为了显示清晰。

         在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()进行注册。相当于邮局中的lisi.registered(mPostOffice)。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();
	}

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




作者:aomandeshangxiao 发表于2012-5-18 23:34:54 原文链接
阅读:27 评论:2 查看评论

相关 [设计模式 观察者 模式] 推荐:

浅学设计模式之观察者模式及在android中的应用

- - CSDN博客推荐文章
        最近在学习下设计模式,而加深学习的不错的方法就是把心得写出来吧. 现在自己看的书是《head.Frist设计模式》这本书.         观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是 软件设计模式的一种.

Scala设计模式

- - ITeye博客
       我的话: 在国外网站上看到一篇文章,里面详细描述了很多设计模式,并且用Java及Scala两种语言描述,清晰的让我们看到各种常规的设计模式,在Scala中是如何在语言特性层面直接支持的. 基于文章很nice,我利用今天的空闲时间将其翻译,希望大家能一起学习,讨论. 翻译比较倡促,也就两小时左右,有何不当,请在下面留言指出.

Spring设计模式

- - 行业应用 - ITeye博客
springMVC通常采用属性注入的IOC方式和AOP织入方式相结合实现依赖注入 同时使用强制代理方式,代理类或者接口. 这里又涉及到单例模式(注入的类或者接口在容器中只存在一个)、工厂模式(通过反射实现类实例化过程的公用化)、楼上所说的装饰模式属于AOP织入的一部分. 想了解spring先从IOC和AOP开始吧.

Java观察者模式

- - CSDN博客架构设计推荐文章
闲话少说,贴出code供参考:. /** * @author Verphen * @date 2013年10月4日 下午11:02:21 */ package org.verphen.observer; /*抽象被观察者角色*/ public interface IWitched {. /* 被观察者 发生变化,通知观察者 */.

“另类” 设计模式

- Sean Lee - 酷壳 - CoolShell.cn
下面这篇文章来自这里:http://www.lsd.ic.unicamp.br/~oliva/fun/prog/resign-patterns,这篇文章有点意思了,山寨了我们著名的Design Pattern. 这篇文章并不是很容易翻译,也许我翻译的不好,大家多指正. 另外,这篇文章将失去原有的趣味在于其使用了经典设计模式的单词很相似的单词,一走眼你还以为是正二八经的设计模式.

【译】屏幕设计模式

- 志强 - 所有文章 - UCD大社区
模式是广泛适用的解决一般问题的解决方案. 在开发应用程序过程中,无论是面对抽象还是实际问题,模式都大有用处. 而标准屏幕模式对于优秀的Web程序甚至企业级软件都很有帮助. 摘要/细节(Master/Detail). 摘要/细节模式可横向也可竖向. 该模式是满足用户既停留在一个页面又可浏览多个条目需求的典范.

设计模式之代理模式(Proxy)

- - 博客园_首页
这段时间一直忙于期末考试,好久没来博客园了,现在好了,终于考完了,也该过上正常的日子了. 开学就是大四的学生了,时间过的可是真快啊,转眼间大学四年已经接近尾声了. 回想大学这三年,成绩还可以吧(年级前10%),参加过各种竞赛(acm,数学建模等等),学生会也呆过(打了一年的酱油),好哥们也有那么五六个(希望以后能在一个城市发展,大学期间的宝贵财富啊),另外所谓的大学生创新实践项目也搞了一个(就算开阔一下视野吧,大学能生有什么创新呢.

Java中的观察者模式

- - CSDN博客编程语言推荐文章
这个接口定义了一个update()方法,当被观察者对象的状态发生变化时,这个方法就会被调用. 这个方法的实现类应当调用每一个被观察者对象的notifyObservers()方法,从而通知所有的观察对象. 被观察者类都是java.util.Observable类的子类. 这个类主要提供下面几个方法:.

设计模式原则总结

- - IT技术博客大学习
0、单一职责原则(SRP) 就一个类而言,应该仅有一个引起它变化的原因. 一、”开放-封闭”原则(OCP) 在软件设计模式中,这种不能修改,但可以扩展的思想也是最重要的一种设计原则. 即软件实体(类、模板、函数等等)应该可以扩展,但是不可修改. 【通俗】:设计的时候,时刻考虑,尽量让这个类是足够好,写好了就不要去修改了,如果新需求来,我们增加一些类就完事了,原来的代码能不动则不动.

Web应用的缓存设计模式

- - robbin的自言自语
从10年前的2003年开始,在Web应用领域,ORM(对象-关系映射)框架就开始逐渐普及,并且流行开来,其中最广为人知的就是Java的开源ORM框架Hibernate,后来Hibernate也成为了EJB3的实现框架;2005年以后,ORM开始普及到其他编程语言领域,其中最有名气的是Ruby on rails框架的ORM - ActiveRecord.