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

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

观察者模式的定义:观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新

考虑到如下一个场景,记者每次获得独家新闻,都需要通知人民日报和新华日报,Hi,i have a new message!

public class SpecificRepoter {	private PeopleDaily pd;	private XinHuaDaily xd;	private String msg;		public Repoter(){		this.pd = new PeopleDaily();		this.xd = new XinhuaDaily();	}		public void gotNewNews(String msg){		this.msg = msg;	}		public void notifyNewspaperOffice(){		pd.update(msg);		xd.update(msg);	}}
public class XinHuaDaily {	public void update(String message){		System.out.println("XinHua Daily got the new news!");	}}
public class PeopleDaily {	public void update(String message){		System.out.println("People Daily got the new news!");	}}

由于记者和报社之间的合约关系由记者来维护,维护方式为:和记者签订合同的报社作为记者的属性,也即具体报社类和记者类紧耦合,故合约关系的变化必然导致记者类的变化:

现在记者和人民日报的合约到期,同时和环球时报签订了新合约

顺承前面的设计方式,必须要修改记者类以适应合约关系的改变:

public class SpecificRepoter {	private XinHuaDaily xd;	private GlobalTimes gt;	private String msg;		public Repoter(){		this.xd = new XinHuaDaily();		this.gt = new GlobalTimes();	}		public void gotNewNews(String msg){		this.msg = msg;	}		public void notifyTheNewspaperOffice(){		xd.update(msg);		gt.update(msg);	}}
public class GlobalTimes {	public void update(String message){		System.out.println("Global Times got the new news!");	}}

显然这种设计的可扩展性很低,本质原因是记者类和具体报社类紧耦合

要提高程序的扩展性,则要从降低记者类和具体报社类的耦合度来下手

设计一

1,抽象出记者接口和报社抽象类,针对接口编程

2,记者与报社之间的合约关系不再通过记者组合具体报社类来维护。设计一个List<NewspaperOffice>来保存和记者签订合同的报社(本质原则也是封装可变化部分,但只是封装至一个List属性中,而没有单独封装至一个类中,不像设计二那么彻底),记者将不和任何特定的报社类相耦合

public interface Repoter {	public void registerNewspaperOffice(NewspaperOffice no);	public void removeNewspaperOffice(NewspaperOffice no);	public void notifyNewspaperOffice();}
public class SpecificRepoter implements Repoter {	private String msg;	private List
relation; public SpecificRepoter(){ relation = new ArrayList
(); } public void registerNewspaperOffice(NewspaperOffice no) { if(!relation.contains(no)){ relation.add(no); } } public void removeNewspaperOffice(NewspaperOffice no) { if(relation.contains(no)){ relation.remove(no); } } public void notifyNewspaperOffice() { if(null != relation && relation.size()>0){ for(NewspaperOffice no : relation){ no.update(this.msg); } } } public void getNewNews(String msg){ this.msg = msg; notifyNewspaperOffice(); }}
public abstract class NewspaperOffice {	protected Repoter repoter;	protected String newMsg;		public void register(){		repoter.registerNewspaperOffice(this);	}		public void remove(){		repoter.removeNewspaperOffice(this);	}		public abstract void update(String newMsg);}
public class PeopleDaily extends NewspaperOffice{	public PeopleDaily(Repoter repoter){		this.repoter = repoter;	}		public void update(String newMsg) {		this.newMsg = newMsg;		System.out.println("People Daily got "+newMsg);	}}

具体报社类设计拥有register()和remove()方法以提高使用时的灵活性,当然这不是必要的

无论合约关系如何变化,SpecificReport类都不需要重新设计修改,相当方便

public class Test {	public static void main(String[] args){		Repoter repoter = new SpecificRepoter();		NewspaperOffice n1 = new GlobalTimes(repoter);		NewspaperOffice n2 = new XinHuaDaily(repoter);		NewspaperOffice n3 = new PeopleDaily(repoter);		n1.register();		n2.register();		repoter.registerNewspaperOffice(n3);				repoter.getNewNews("news coming!");		n3.remove();		repoter.removeNewspaperOffice(n2);		repoter.getNewNews("another news coming!");	}}
Global Times got news coming!XinHua Daily got news coming!People Daily got news coming!Global Times got another news coming!

总结一下:

我们再来看看观察者模式:

当然具体实现方式上可以有多种变化

设计二,将记者和报社的合约关系独立出去,单独维护(封装),此时记者类不但与具体报社类解耦,甚至与报社抽象类解耦:

public abstract class Repoter {	protected String msg;	protected Relation relation;		public abstract void getNewNews(String msg);}
public class SpecificRepoter extends Repoter {	public SpecificRepoter(Relation relation){		this.relation = relation;	}		public void getNewNews(String msg){		this.msg = msg;		relation.notifyNewspaperOffice(msg);	}}
public interface Relation {	public void registerNewspaperOffice(NewspaperOffice no);	public void removeNewspaperOffice(NewspaperOffice no);	public void notifyNewspaperOffice(String msg);}
public class SpecificRelation implements Relation {	private List
relation; public SpecificRelation(){ relation = new ArrayList
(); } public void registerNewspaperOffice(NewspaperOffice no) { if(!relation.contains(no)){ relation.add(no); } } public void removeNewspaperOffice(NewspaperOffice no) { if(relation.contains(no)){ relation.remove(no); } } public void notifyNewspaperOffice(String msg) { if(null != relation && relation.size()>0){ for(NewspaperOffice no : relation){ no.update(msg); } } }}
public abstract class NewspaperOffice {	protected Relation relation;	protected String newMsg;		public void register(){		relation.registerNewspaperOffice(this);	}		public void remove(){		relation.removeNewspaperOffice(this);	}		public abstract void update(String newMsg);}
public class PeopleDaily extends NewspaperOffice{	public PeopleDaily(Relation relation){		this.relation = relation;	}		public void update(String newMsg) {		this.newMsg = newMsg;		System.out.println("People Daily got "+newMsg);	}}

 

转载于:https://www.cnblogs.com/sean-zou/archive/2013/05/25/3710056.html

你可能感兴趣的文章
(文件过多时)删除目录下全部文件
查看>>
T-SQL函数总结
查看>>
python 序列:列表
查看>>
web移动端
查看>>
pythonchallenge闯关 第13题
查看>>
linux上很方便的上传下载文件工具rz和sz使用介绍
查看>>
React之特点及常见用法
查看>>
【WEB前端经验之谈】时间一年半,或沉淀、或从零开始。
查看>>
优云软件助阵GOPS·2017全球运维大会北京站
查看>>
linux 装mysql的方法和步骤
查看>>
poj3667(线段树区间合并&区间查询)
查看>>
51nod1241(连续上升子序列)
查看>>
SqlSerch 查找不到数据
查看>>
集合相关概念
查看>>
Memcache 统计分析!
查看>>
(Python第四天)字符串
查看>>
个人介绍
查看>>
使用python动态特性时,让pycharm自动补全
查看>>
MySQL数据库免安装版配置
查看>>
你必知必会的SQL面试题
查看>>