设计模式之观察者模式(Observer)

其实我以前也有学习过设计模式,也写过一些代码。这次在看代码时,发现设计模式使用的泛滥,想想我的设计模式学习的不够扎实,所以重新拾起,把以前没有学习的设计模式学习一遍,把学习过的设计模式在重温一遍。第一篇我选择的是观察者模式。我在项目代码中看到这个模式,项目中的使用大概说一下:服务器与客户端的交互,服务器端的代码使用了观察者模式,作用是:当用户发送请求以后,通过注册的Manager管理类来调用相应的方法处理用户的请求。

这里做一个报社新闻给用户推送新闻的案例(当报社推送新闻的时候,所有订阅了报社的读者可以阅读报纸):

方案一:采用Java自带的观察者接口实现,如下:

首先是报社类,继承了Observable,需要注意的是在通知观察者之前需要setChanged一下,因为notifyObservers()在调用时,需要知道自己的观察者发生了改变,而这个方法是通过Changed变量来判断是否为true,如果不为true,直接return,具体可以查看源码。所以我们需要setChanged,让hasChanged方法返回true。具体可以看notifyObservers()的定义说明

import java.util.Observable;

public class Publisher extends Observable {

	public void updateNews(String str) {
		setChanged();
		notifyObservers(str);
	}
}


然后是用户读者:(这里做了2个读者)需要实现Observer接口,并实现接口内部的具体方法update().实现这样的update方法,主要是因为在notifyObservers函数中对这个update方法进行了调用。这也是设计模式的精髓所在。我们可以查看Observable的具体实现,从而知道如何设计一个抽象的观察者。

import java.util.Observable;
import java.util.Observer;


public class Reader_1 implements Observer{

	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub
		if(arg instanceof String){
			System.out.println("I'm Reader_1,"+(String)arg);
		}
	}

}
import java.util.Observable;
import java.util.Observer;


public class Reader_2 implements Observer{

	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub
		if(arg instanceof String){
			System.out.println("I'm Reader_2,"+(String)arg);
		}
	}

}


然后是我们的测试Main类:需要做的是创建出版社,读者1,读者2。

读者1,读者2都订阅报社的报纸。第一次推送。

然后读者1退订报纸,报社第二次推送。

public class Main {
	public static void main(String[] args) {
		Publisher p = new Publisher();
		Reader_1 r1 = new Reader_1();
		Reader_2 r2 = new Reader_2();
		
		p.addObserver(r1);
		p.addObserver(r2);
		
		System.out.println("当前读者数:"+p.countObservers());
		System.out.println("第一次推送消息:");
		p.updateNews("CCTV-5 SportNews");
		
		p.deleteObserver(r1);
		
		System.out.println("
当前读者数:"+p.countObservers());
		System.out.println("第二次推送消息:");
		p.updateNews("News for Car");
	}
}


运行结果:

当前读者数:2
第一次推送消息:
I'm Reader_2,CCTV-5 SportNews
I'm Reader_1,CCTV-5 SportNews

当前读者数:1
第二次推送消息:
I'm Reader_2,News for Car

==============================================================================================================================

方案二:自己动手,丰衣足食。我们需要实现的是抽象报社,抽象读者,具体报社,具体读者,外加一个测试函数即可,

其实跟Java自己实现的观察者接口相差并不多,下面就简单的实现它的基础功能,如下所示:

思路清晰,写代码:

package demo;

import java.util.Vector;

public class AbstractPublisher {
	// 库函数采用的是Vector来实现对注册读者的存储,我们也走大神的路
	Vector<AbstractReader> vector;

	public AbstractPublisher() {
		vector = new Vector<AbstractReader>();
	}

	public boolean addReader(AbstractReader ar) {
		if (vector.add(ar))
			return true;
		return false;
	}

	public boolean deleteReader(AbstractReader ar) {
		if (vector.remove(ar))
			return true;
		return false;
	}

	public void notifyReaders(String news) {
		for (AbstractReader ar : vector) {
			ar.readNews(news);
		}
	}
}
package demo;

public interface AbstractReader {
	public void readNews(String news);
}
package demo;

public class Publisher extends AbstractPublisher {
	//推送新闻给读者
	public void pushNews(String news) {
		notifyReaders(news);
	}
}
package demo;
 

public class Reader_Joy implements AbstractReader{

	@Override
	public void readNews(String news) {
		// TODO Auto-generated method stub
		System.out.println("I'm Reader_Joy " + news);
	}

}
package demo;

public class Reader_Tom implements AbstractReader{

	@Override
	public void readNews(String news) {
		// TODO Auto-generated method stub
		System.out.println("I'm Reader_Tom "+news);
	}

}



package demo;

public class Main {
	public static void main(String[] args) {
		Publisher p = new Publisher();
		Reader_Joy joy = new Reader_Joy();
		Reader_Tom tom = new Reader_Tom();
		p.addReader(joy);
		p.addReader(tom);
		System.out.println("第一次推送消息:");
		p.pushNews("News Of Game");
		
		p.deleteReader(joy);
		System.out.println("第二次推送消息:");	
		p.pushNews("News Of City");
	}
}


运行结果:

第一次推送消息:
I'm Reader_Joy News Of Game
I'm Reader_Tom News Of Game
第二次推送消息:
I'm Reader_Tom News Of City

基本的代码实现就是这样,也许还有错误,但是观察者的基本思想就此理清楚了。

核心部分:1)报社如何存储注册的读者

2)报社如何通知注册的读者

3)如何使用接口和继承的方式组织结构。

项目源代码:http://www.kuaipan.cn/file/id_132802506211221411.htm?source=1

原文地址:https://www.cnblogs.com/vokie/p/3602078.html