`
mrzhufeng
  • 浏览: 8984 次
  • 性别: Icon_minigender_1
  • 来自: 安徽
社区版块
存档分类
最新评论

我对观察者模式的理解

阅读更多

前言

     一直很少动手写文档,觉得自己只是一个新手,对很多技术点或者概念理解的不透彻,没多少自信。二来,做程序遇到困难时,在论坛上找到的几乎都是通篇的代码,只能一行行解读代码,自己自圆其说。我不太喜欢这种模式,但是又不知道如何找到详细的资料,天天百度,费力不讨好。在图书馆找参考书,大多都是些基础的东西,也没什么帮助。

    昨天,老师布置了一些作业,问我们应不应该强制?回来后我想了想,还是觉得不该强制,如果你爱JAVA,你自己会花时间在上面的。写文档倒是很有必要的。写文档,一来可以记录你的学习历程,二来可以暴露一些问题,如果你讲不清楚一个问题,很有可能时因为你对该问题的理解不透彻。

  

   今天,我要叙述的内容是观察者模式,也称发布/订阅模式,监听器模式

  

观察者模式是软体设计模式的一种。在此种模式中,一个目标物件(被观察者)管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。

 

   叙述该问题,通篇叙述不如通过实例来的易理解,不用实例,估计我也讲不清楚

  

   例:给一个JFrame上的JTree添加节点,通过线程给JTree添加5个节点

 

1.直接调用模式

     学习这么久,老师从没有讲过搭建模型,记得在写五子棋游戏的时候,那时候写的是郁闷的很,每添加一个功能时,都要修改好几个类。类与类的耦合非常高。    

    实现JFrame的JTree上添加节点:

    思路:用线程来模拟给JTree添加节点,在线程的构造器中传入JTree对象。

     

/**********************
 *此类为消息类,用来作为树节点
 */
public class Msg {

	private String text;
	
	public Msg(String text){
		this.text = text;
	}
	
	//重写toString方法,设置节点显示内容
	public String toString(){
		return this.text;
	}
}

 

  线程类:

    

public class TestThread extends  Thread{

	private JTree tree;
	
	public TestThread(JTree tree){
	    //传入JTree对象   
		this.tree = tree ;
	}
	
	
	public void run(){
		
		DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
		
		for(int i=0;i<5;i++){
			
			Msg msg = new Msg("第"+(i+1)+"个节点");
			DefaultMutableTreeNode node = new DefaultMutableTreeNode(msg);
			//添加节点
			root.add(node);
			//刷新树
			javax.swing.SwingUtilities.updateComponentTreeUI(tree);
			//延时1S
			try{
				Thread.sleep(1000);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
	

 测试界面类:

  

	public static void main(String[] args){
		
		JFrame fr = new JFrame("Test_1");
		fr.setSize(300, 300);
		fr.setDefaultCloseOperation(3);
		fr.setLayout(new FlowLayout(FlowLayout.LEFT));
		
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("根节点");
		JTree tree = new JTree(root);
		fr.add(tree);
		
		new TestThread(tree).start();
		
		fr.setVisible(true);
		
	}

 

总结1:软件是应用户需要而编写的,肯定会经常修改。这种模式由于界面类和实现类之间的高耦合,要改界面类和实现

       类都要改, 不利于程序的修改和扩展。

          怎样才能避免这种牵一发动全身的问题呢?

           想想,如果将具体对象间的依赖关系转化为接口实现的抽象关系会怎样,就可将界面类和实现类分别封装,使相互

       独立,各自修改互补影响。对于本例,在线程中添加一个监听器队列,当产生事件时通知队列中的各监听器即可,这

        需要有添加,移除,通知监听器的方法。

 

          可将上面的代码修改一下

观察者模式

     首先需要定义消息处理接口

public interface InListener {

	public void actionPerformed(Msg msg);
	
}

   根据需要编写实现类,本例中:

   MyJTreeListener

  

public class MyJTreeListener implements InListener{

	
	private JTree tree;
	private DefaultMutableTreeNode root;
	
	public MyJTreeListener(JTree tree){
		
		this.tree = tree;
		root = (DefaultMutableTreeNode) tree.getModel().getRoot();
		
	}
	
	
	public void actionPerformed(Msg msg) {
		
		DefaultMutableTreeNode node = new DefaultMutableTreeNode(msg);
	    root.add(node);
	    javax.swing.SwingUtilities.updateComponentTreeUI(tree);
	}

}

 线程类:

 

public class TestThread extends  Thread{
    
	//监听器队列
	private ArrayList<InListener> list ;
	
	public TestThread(){
	    //初始化监听器队列
		list = new ArrayList();
	}
	
	
	public void run(){
		
			for(int i=0;i<5;i++){
				
				Msg msg = new Msg("第"+(i+1)+"条消息");
				//通知各监听器
				this.fireInListener(msg);
				
				//延时1S
				try{
					Thread.sleep(1000);
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		
	}
	
	/***********************8
	 * 通知所有消息监听器
	 * @param msg:消息
	 */
	public void fireInListener(Msg msg){
		
		for(int i=0;i<list.size();i++){
			InListener listener = list.get(i);
			listener.actionPerformed(msg);
		}
	}
	
	/***************************
	 * 添加事件监听器
	 * @param l:要添加的监听器
	 * @return:添加结果
	 */
	public boolean addListener(InListener l){
		
		return list.add(l);
		
	}
	/****************************
	 * 移除事件监听器
	 * @param l:要移除的监听器
	 * @return:移除结果
	 */
	public boolean removeListener(InListener l){
		
		return list.remove(l);
	}
	
	

 测试:

  

	public static void main(String[] args){
		
		JFrame fr = new JFrame("Test_2");
		fr.setSize(300, 300);
		fr.setDefaultCloseOperation(3);
		fr.setLayout(new FlowLayout(FlowLayout.LEFT));
		
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("根节点");
		JTree tree = new JTree(root);
		fr.add(tree);
		
		TestThread nt = new TestThread();
		//注册监听器
		nt.addListener(new MyJTreeListener(tree));
		nt.start();
		
		
		fr.setVisible(true);
		
	}

 总结2:这样,线程对象和具体的事件处理对象就可以相互独立的修改    但实际上这是一种具体对抽象的关系,可以进一步将事件产生类(本例中为线程)进行抽象,变为抽象对抽象的关系,毕竟现实中的事件产生可以有很多种情况,往往风马牛不相及。

 

    只需再定义一个事件产生接口即可:

    InEventSource

   

public interface InEventSource {

	public ArrayList<InListener> list = new ArrayList();
	
	public boolean addListener(InListener l);
	
	public boolean removeListener(InListener l);
	
	public void fireInListener(Msg msg);
	
	
}

 

线程类:

  

public class TestThread extends  Thread implements InEventSource{

	
	public void run(){
		
			for(int j=0;j<5;j++){
				
				Msg msg = new Msg("第"+(j+1)+"条消息");
				
				this.fireInListener(msg);
				
				//延时1S
				try{
					Thread.sleep(1000);
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		
	}
	
	
	public void fireInListener(Msg msg){
		
		for(int i=0;i<list.size();i++){
			InListener listener = list.get(i);
			listener.actionPerformed(msg);
		}
	}
	
	
	public boolean addListener(InListener l){
		
		return list.add(l);
		
	}
	
	public boolean removeListener(InListener l){
		
		return list.remove(l);
	}
	

 

测试不变

 

总结3:观察者模式所进行的工作就是解耦,就是将具体的对象之间的关系进行抽象,变为抽象对抽象的关系,降低具体对象间的依赖性,从而实现良好的修改,扩充性。其实,就是让我们懂得封装的重要性,教我们如何封装。

 

 

什么时候应该采用观察者模式

     我觉得,当一个对象改变时,同时要改变其他对象,而且不知道要改变多少其他对象时,应该考虑采用观察者模式。

 

 

由于我的水平有限,讲的不是很清楚,如果有错的,或是不好的地方,欢迎指出批评。

 

附上 《大话设计模式》下载链接 书中第14章有很生动的讲解

http://dl.iplaysoft.com/files/742.html

分享到:
评论
1 楼 简单线条 2011-01-18  
不错

相关推荐

    java观察者模式观察者模式

    观察者模式是设计模式中的一种行为模式,它在Java编程中有着广泛的应用。该模式的主要目的是定义对象...在实际开发中,理解并合理运用观察者模式,能够有效地实现对象之间的交互和通信,提升代码的灵活性和可维护性。

    设计模式实现——观察者模式

    观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现发布-订阅...

    java 设计模式 观察者模式 简单实例 包括测试test类

    观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现事件驱动或者发布...

    Qt设计模式之观察者模式

    本篇文章将深入探讨Qt中的观察者模式(Observer Pattern),这是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 观察者模式的核心...

    iOS 设计模式 观察者模式

    观察者模式,也被称为发布-订阅(Publish-Subscribe)模式,是软件设计中的一种行为模式。...无论是使用Apple提供的API还是自定义实现,理解并熟练运用观察者模式都能提升你的编程技能和项目质量。

    观察者模式模版和例子

    观察者模式(Observer Pattern)是设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式常用于实现事件驱动的系统或者...

    设计模式-观察者

    观察者模式(Observer Pattern)是行为设计模式的一种,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 观察者模式的核心思想是发布-订阅模型,其中...

    设计模式之观察者模式

    通过学习观察者模式,你不仅可以提高代码的可维护性和可扩展性,还能更好地理解和利用面向对象设计的原则,如开闭原则(对扩展开放,对修改关闭)。此外,了解并熟练运用观察者模式还有助于你理解和使用其他设计模式...

    观察者模式练习

    观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于事件驱动的系统或者...

    [行为型模式] 观察者模式的理解

    .edx和.pdf文件可能包含了这些图形的详细表示,对于深入理解观察者模式的结构和作用非常有帮助。 总的来说,观察者模式是一种强大的设计模式,能够有效地管理对象间的通信,提高系统的灵活性和可扩展性。在实际开发...

    运用MVC模式及观察者模式的java小程序

    在Java编程领域,设计模式是解决常见问题的模板或最佳实践。在这个名为“运用MVC模式及观察者模式的java小程序”的项目中,我们重点探讨了两种经典的...分析和学习这些代码将有助于深入理解MVC和观察者模式的实际应用。

    java 了解观察者模式

    观察者模式,也被称为发布-订阅(Publish-Subscribe)模式,是软件设计模式中的行为模式之一,主要用于对象间的一...理解并熟练运用观察者模式,可以提升代码的可维护性和复用性,使得程序设计更加符合面向对象的原则。

    Java内置观察者模式

    观察者模式(Observer Pattern)是设计模式中的一种行为模式,它允许一个对象,当其状态发生改变时,能够自动通知所有依赖它的其他对象。在Java中,这种模式已经被内置到语言核心,使得开发者可以轻松地实现事件驱动...

    观察者模式示例源代码

    Java、C#等面向对象语言都内置了对观察者模式的支持,例如Java的`java.util.Observable`和`java.util.Observer`,C#的`System.ComponentModel.INotifyPropertyChanged`等。 总结来说,观察者模式是一种强大的设计...

    观察者模式源码

    观察者模式(Observer Pattern)是软件设计模式的一种,属于行为型模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。在Java中,观察者模式主要通过...

    观察者模式代码

    观察者模式是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在Java或其他面向对象语言中,...理解并熟练运用观察者模式,有助于提高代码的可维护性和可扩展性。

    观察者模式简单例子

    在这个"观察者模式简单例子"中,我们将通过一个天气预报版的例子来深入理解这一模式。 在《Head First设计模式》第2章的天气预告版示例中,有三个主要角色:Subject(主题)、Observer(观察者)和ConcreteSubject...

    观察者模式Demo

    观察者模式(Observer Pattern)是设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式常用于实现事件驱动的系统,...

Global site tag (gtag.js) - Google Analytics