观察者模式(Observer Patten)

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

考虑到如下一个场景,记者每次获得独家新闻,都需要通知人民日报和新华日报,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<NewspaperOffice> relation;
	
	public SpecificRepoter(){
		relation = new ArrayList<NewspaperOffice>();
	}

	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<NewspaperOffice> relation;
	
	public SpecificRelation(){
		relation = new ArrayList<NewspaperOffice>();
	}

	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);
	}
}


 

posted @ 2013-05-25 11:53  心意合一  阅读(174)  评论(0编辑  收藏  举报