博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
观察者模式
阅读量:6124 次
发布时间:2019-06-21

本文共 4367 字,大约阅读时间需要 14 分钟。

观察者模式(Observer Pattern)在项目中常常会被使用到。也被叫做公布订阅模式,也就是说  观察者 =  公布者 + 订阅者
GoF的《设计模式》中对观察者是这样描写叙述的:
Define a one-to-many dependency between objects so that when one object changes state。 all its dependents are notified and updated automatically。
意思就是。定义一个对象之间的一对多的依赖关系,使得当一个对象的状态发生改变的时候,它的全部依赖对象可以自己主动地被通知以及被更新。这里须要注意原句被动语态的使用。依赖对象不是主动检測。而是被通知和被更新。
观察者模式的UML
能够发现,观察者模式共涉及4种角色:
抽象主题角色(Subject):也就是被观察者角色,它能够在自己的内部加入或删除一个观察者对象,这些观察者对象将作为它的通知对象。
抽象观察者角色(Observer):为全部的观察者对象定义一个共同的接口,指定同样的通知规范。
详细主题角色(Concrete Subject):实现抽象主题角色,是详细真实的被观察者。

详细观察者角色(Concrete Observer):实现抽象观察者角色,是详细真实的观察者。一般有多个,能够定义自己收到被观察者通知后运行的业务逻辑。
事实上再抽象一点划分。观察者模式仅仅有两个角色:观察者和被观察者。也就是1个被观察者相应多个观察者的依赖,这也是为什么观察者 = 公布者 + 订阅者。
当中抽象主题角色(Subject)的代码例如以下
public interface Subject {		//注冊观察者对象o	public void attach(Observer o);	//删除观察者对象o	public void detach(Observer o);	//通知观察者	public void notifyObserver();	}
抽象主题角色(被观察者角色)定义了添加和删除观察者的方法,详细的被观察者须要维护一个观察者列表,当被观察者的状态发生变化的时候,回去主动的通知列表中的观察者。
抽象观察者角色(Observer)的代码实现:
public interface Observer {	//接收到通知的操作	public void update();	}
仅仅有一个update方法,用于接收到来之被观察者通知的时候採取的更新操作,这种方法一般由被观察者调用。
以下是这两个接口的详细实现,也就是详细主题角色(详细被观察者角色)、详细观察者角色
import java.util.LinkedList;import java.util.List;public class ConcreteSubject implements Subject {	//用于保存自己的注冊对象	private List
observerList = new LinkedList
(); //方便常常的插入和删除操作 /** * 注冊一个观察者 */ @Override public void attach(Observer o) { // TODO Auto-generated method stub observerList.add(o); } /** * 取消一个观察者 */ @Override public void detach(Observer o) { // TODO Auto-generated method stub observerList.remove(o); } /** * 通知观察者 */ @Override public void notifyObserver() { // TODO Auto-generated method stub for(Observer obs : observerList ) { obs.update(); //逐个通知观察者 } } }
public class ConcreteObserver implements Observer {	/**	 * 接到通知的逻辑	 */	@Override	public void update() {		// TODO Auto-generated method stub			}	}
观察者模式的详细实例
一个典型的样例就是消息订阅,比方,我们在关注了一个某晚报微信公众号,然后每天公众号给我们发送订阅的新闻,这里公众号就是一个被观察者角色,而我们订阅者就是观察者角色
抽象主题角色Subject,也就是公众号的简单抽象定义:
public interface PublicOffcial {		//注冊订阅消息的用户		public void attach(WechatUser user);				//取消订阅消息的用户		public void detach(WechatUser user);				//向用户发送订阅		public void notifyObserver(String news);	}
抽象观察者角色,这里也就是微信订阅用户的简单抽象
public interface WechatUser {	public void readNews(String news);	}
实现详细主题角色(真实被观察者),这里是
XX晚报的公众号
import java.util.LinkedList;import java.util.List;public class PublicOffcialXXNewPaper implements PublicOffcial {	//已订阅用户的列表	private List< WechatUser> list = new LinkedList
(); /** * 当用户订阅时。增加列表 */ @Override public void attach(WechatUser user) { if( ! list.contains(user)) list.add(user); } /** * 用户取消订阅时,从列表清除 */ @Override public void detach(WechatUser user) { if(list.contains(user)) list.remove(user); } /** * 通知订阅者 */ @Override public void notifyObserver(String news) { for(WechatUser user : list ) { user.readNews(news); } } /** * 报社某天的公布新闻工作,包含发送给微信订阅者,可能还要更新站点 * @param news */ public void ReleaseNews(String news) { //something to do e.g: update website.. System.out.println("报社公布今日新闻【" + news + "】"); notifyObserver(news); } }
详细观察者角色,也就是订阅消息的用户
public class NewsPaperFan implements WechatUser {	private String name;		public NewsPaperFan(String name) {		// TODO Auto-generated constructor stub		this.name = name;	}		@Override	public void readNews(String news) {		System.out.println("用户: " + name + "收到订阅的新闻【" + news + "】");	}	}
以上就是关于消息订阅的观察者模式的实现。
client測试类:
public class Client {	public static void main(String[] args) {		PublicOffcialXXNewPaper newPaper = new PublicOffcialXXNewPaper();		WechatUser user1 = new NewsPaperFan("Tony");		WechatUser user2 = new NewsPaperFan("Jack");		WechatUser user3 = new NewsPaperFan("David");				newPaper.attach(user1);		newPaper.attach(user2);		newPaper.attach(user3);				newPaper.ReleaseNews("苹果即将推出IPhone6...");			}	}
程序输出:
报社公布今日新闻【苹果即将推出IPhone6...】用户: Tony收到订阅的新闻【苹果即将推出IPhone6...】用户: Jack收到订阅的新闻【苹果即将推出IPhone6...】用户: David收到订阅的新闻【苹果即将推出IPhone6...】
综上,能够看出观察者模式的
一些长处
  • 观察者和被观察者之间是抽象耦合的。

    被观察者仅仅能观察到观察者的接口层定义。而不知道自己通知的观察者的详细类型,它们之间属于不同的抽象层面,没有紧密的耦合,easy扩展。

  • 支持像消息订阅这种广播通信。
一些缺点
  • 假设被观察者须要通知多个观察者,或者通知过程时候耗时,那么上述被观察者的通知过程将会很耗时。

    对于这一点。假设通知的过程是相互独立的任务。那么能够使用多线程去完毕,使通知在子线程中完毕。

  • 假设拥有多个被观察者。而且它们之间存在依赖关系,那么easy发生循环调用。

观察者模式的应用场景
  • 广播链问题。

    一个对象事实上既能够作为观察者也能够作为被观察者,这样消息像在广播链中传递。可是须要注意假设链的长度假设过程。就会变的复杂。难以控制。

  • 异步处理的问题。

    在异步处理过程须要考虑线程安全和队列的问题。

你可能感兴趣的文章
cmake总结
查看>>
数据加密插件
查看>>
linux后台运行程序
查看>>
win7 vs2012/2013 编译boost 1.55
查看>>
IIS7如何显示详细错误信息
查看>>
Android打包常见错误之Export aborted because fatal lint errors were found
查看>>
Tar打包、压缩与解压缩到指定目录的方法
查看>>
新手如何学习 jQuery?
查看>>
配置spring上下文
查看>>
Python异步IO --- 轻松管理10k+并发连接
查看>>
mysql-python模块编译问题解决
查看>>
Oracle中drop user和drop user cascade的区别
查看>>
【Linux】linux经常使用基本命令
查看>>
HTML模块化:使用HTML5 Boilerplate模板
查看>>
登记申请汇总
查看>>
Google最新截屏案例详解
查看>>
Office WORD如何取消开始工作右侧栏
查看>>
Android Jni调用浅述
查看>>
CodeCombat森林关卡Python代码
查看>>
第一个应用程序HelloWorld
查看>>