`
SurpriseLee
  • 浏览: 7270 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

监听器模式(生产消费模型)

 
阅读更多
    鲁迅有言:世上本没有路,只是走的人多了,也就成了路。不知道是历史的巧合,还是鲁迅的未卜先知。他的昔日之言,竟会在N年后,发出不一样的生命活力。
    在软件设计中,设计模式就是如同此理。它是经验的传承,,并不成体系,它是被前任发现,经过总结形成了一套某一类问题的一般性解决方案,而不是被设计出来的定性规则,它不像算法那样可以照搬照用。
    设计模式关注的终点在于通过经验提取的“准则或指导方案”在设计中的应用,因此,在不同层面考虑问题的时候就形成了不同问题域上的模式。模式的目标是吧共同的问题中不变部分和变化部分分离出来。不变的部分就构成了模式。因此,模式是一个经验提取的“准则”,并且在一次一次的时间中得到验证。不同的层次有不同的模式,小到语言的实现,大到架构。在不同的成面上,模式提供不同层面的指导。
    软件系统设计的目标是:高内聚,低耦合;
    所谓耦合,即不同的模块拼装到一起,产生相互依赖的关系。
    所谓高耦合,即不同模块之间连接点很多,造成错综复杂的连接关系,修改程序时牵一发则动全身。
    所谓低耦合,即模块层次化,我觉得理想的效果是,每一层的模块只与它上一层和下一层的模块进行耦合,同层之间的模块是没有交互的。
    通过一个聊天室项目,在具体分析监听器模式:
    在一般的设计中,我们会通过将文本域传给通信模块,在通信模块中把消息显示到文本域上。这样做,固然能实现聊天室的基本功能。但是,如果要对界面进行改动的话,需要改动通信模块,修改起来就会很蛋疼。
     而通过监听器模式,能实现通信模块与监听器部分代码的有效分离了,从而达到降低维护难度的目的。
     对一个按钮来说,事件源是按钮,监听器是动作监听器。
     对一个聊天室来说,事件源是通信模块,监听器须自己实现。
     监听器模式实现步骤:
     1. 定义一个时间监听器接口;
    
package 监听器模式;

/**
 * 消息监听器接口
 * @author SurpriseLee
 *
 */
public interface IMsgReceiveListener {
	public void receiveMsg(Message msg);
	
}

     2. 编写消息事件监听器的实现类;
    
package 监听器模式;

import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;

/**
 * 自定义监听器实现Listener接口
 * @author SurpriseLee
 *
 */
public class NetTree extends JTree implements IMsgReceiveListener {


	// 将消息包装成树上的一个节点对象,加载到树上
	public void receiveMsg(Message msg) 
	{
		// 取得这个树上的根节点
		DefaultMutableTreeNode root = (DefaultMutableTreeNode)this.getModel().getRoot();
		// 将消息包装成新建的节点
		DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(msg);
		root.add(newNode);
		// 刷新界面,将新节点显示在树上
		SwingUtilities.updateComponentTreeUI(this);
	}
	

}

     3. 注册消息监听器;
    
package 监听器模式;

import java.awt.List;
import java.util.ArrayList;

/**
 * @author SurpriseLee
 *
 */
public class NetConnector extends Thread {
	
	// 监听器队列
	private ArrayList<IMsgReceiveListener> listeners = new ArrayList<IMsgReceiveListener>();
	
	public void run()
	{
		int id = 0;
		while(true)
		{
			try 
			{
				Thread.sleep(3000);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			id++;
			Message msg = new Message();
			msg.setId(id);
			msg.setContent("第" + id + "条消息");
			
			// 分发
			fireMsgReceive(msg);
			System.out.println("第" + id + "条消息");
		}
		
	}
	
	// 注册监听器方法
	public void addListener(IMsgReceiveListener listener)
	{
		listeners.add(listener);
		
	}
	
	// 分发消息给所有监听器方法
	private void fireMsgReceive(Message msg)
	{
		for(int i = 0; i < listeners.size(); i++)
		{
			listeners.get(i).receiveMsg(msg);		
		}
		
	}
	

}


       4. 测试主界面代码;
      
package 监听器模式;

import java.awt.List;
import java.util.ArrayList;

/**
 * @author SurpriseLee
 *
 */
public class NetConnector extends Thread {
	
	// 监听器队列
	private ArrayList<IMsgReceiveListener> listeners = new ArrayList<IMsgReceiveListener>();
	
	public void run()
	{
		int id = 0;
		while(true)
		{
			try 
			{
				Thread.sleep(3000);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			id++;
			Message msg = new Message();
			msg.setId(id);
			msg.setContent("第" + id + "条消息");
			
			// 分发
			fireMsgReceive(msg);
			System.out.println("第" + id + "条消息");
		}
		
	}
	
	// 注册监听器方法
	public void addListener(IMsgReceiveListener listener)
	{
		listeners.add(listener);
		
	}
	
	// 分发消息给所有监听器方法
	private void fireMsgReceive(Message msg)
	{
		for(int i = 0; i < listeners.size(); i++)
		{
			listeners.get(i).receiveMsg(msg);		
		}
		
	}
	

}

        5. Message类定义代码;
       
package 监听器模式;

/**
 * Message
 * @author SurpriseLee
 *
 */
public class Message {

	private int id;   // 消息id
	private String content;
	
	public void setId(int id)
	{
		this.id = id;
	}
	
	public void setContent(String content)
	{
		this.content = content;
	}
}

     个人感悟
     监听器模式并不是不涉及到参数的传递,而是选择去传递那些某些属性不变的参数,或则说是传递那些传出模块不需要再次使用的参数。就像是工厂生产的产品,出厂后基本就不会再返厂再加工,工厂只需要关注怎样生产更适合消费者的产品就好,不用去告诉消费者产品的具体生产流程,只要将成型的产品发送给消费者,那么工厂作为生产者身份的任务就已经完成。而消费者只需要关注怎样去消费产品就好,不用去在意更不参与产品的设计生产过程。生产者与消费者这种生产与消费的有效分离,大大提高的软件系统维护的容易性。






分享到:
评论

相关推荐

    C#23种设计模式_示例源代码及PDF

    解释器模式: 给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一 解释器模式 个解释器。 客户端可以使用这个解释器来解释这个语言中的句子。 解释器模式将描述怎样 在 有了一个简单的文法后, ...

    java开发oa系统源码下载-Spring-rabbitMQ:Spring整合消息队列RabbitMQ

    java开发oa系统源码下载 Spring-rabbitMQ 在业务逻辑的异步处理,系统...direct直连交换机通信模型,包括一个direct交换机,三个binding,两个队列,两个消费者监听器,消息只会被投入到routingkey一致的队列中 4.topic

    javaSE代码实例

    16.4.5 “生产者-消费者”案例的实际运行 365 16.4.6 notify方法的使用 366 16.4.7 同步的语句块 367 16.4.8 线程的死锁 369 16.4.9 防止错误的使用wait、notify、notifyAll方法 371 16.5 获取当前正在...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    6.3.2 消息的生产、消费 250 6.3.3 可靠的JMS订阅 251 6.4 JMS消息 253 6.4.1 JMS消息类型 253 6.4.2 JMS消息头和消息属性 253 6.4.3 重用消息对象 254 6.4.4 JMS传递方式和有效时间 255 6.4.5 设置消息的优先级 256...

    python入门到高级全栈工程师培训 第3期 附课件代码

    05 生产者消费者模型 06 第三次作业讲解 第20章 01 上节课回顾 02 装饰器基本理论 03 高阶函数使用 04 函数闭包 05 函数闭包装饰器基本实现 06 函数闭包加上返回值 07 函数闭包加上参数 08 函数闭包补充:解压序列...

    Java典型模块

    第7章 生产者与消费者问题(线程通信知识) 7.1 生产者与消费者原理 7.1.1 项目结构框架分析 7.1.2 项目功能业务分析 7.2 无线程通信的生产者与消费者项目 7.2.1 生产者类 7.2.2 消费者类 7.2.3 储存库类 7.2.4 测试...

    oracle数据库11G初学者指南.Oracle.Database.11g,.A.Beginner's.Guide

    3.4.2 多个监听进程 3.4.3 连接池 3.5 命名方法 3.5.1 目录命名方法 3.5.2 目录信息树 3.5.3 标识名 3.5.4 如何查找目录命名信息 3.5.5 网络服务别名条目 3.5.6 本地命名方法 3.5.7 简单命名方法 3.5.8 外部命名方法...

    Oracle Database 11g初学者指南--详细书签版

    3.4.2 多个监听进程 59 3.4.3 连接池 59 3.5 命名方法 60 3.5.1 目录命名方法 60 3.5.2 目录信息树 60 3.5.3 标识名 61 3.5.4 如何查找目录命名信息 61 3.5.5 网络服务别名条目 61 3.5.6 本地命名方法 62 ...

    JAVA基础课程讲义

    生产者/消费者模式 181 线程回顾总结 184 任务调度(补充内容,了解即可!) 184 思考作业 185 上机作业 185 第十章 网络编程 186 基本概念 186 什么是计算机网络 186 计算机网络的主要功能 186 什么是网络通信协议 ...

    Spring攻略(第二版 中文高清版).part2

    10.6 使用BlazeDS和Spring消费面向消息的服务 421 10.6.1 问题 421 10.6.2 解决方案 422 10.6.3 工作原理 422 10.7 将依赖注入带给你的ActionScript客户 434 10.7.1 问题 434 10.7.2 解决方案 434 ...

    Spring攻略(第二版 中文高清版).part1

    10.6 使用BlazeDS和Spring消费面向消息的服务 421 10.6.1 问题 421 10.6.2 解决方案 422 10.6.3 工作原理 422 10.7 将依赖注入带给你的ActionScript客户 434 10.7.1 问题 434 10.7.2 解决方案 434 ...

    Java开发技术大全 电子版

    8.4.4生产者-消费者问题实例284 8.5本章小结287 第9章运行时类型识别288 9.1RTTI的作用288 9.2用Class类来加载对象289 9.3使用getClass()方法获取类信息290 9.4使用类标记292 9.5使用关键字instanceof判断...

Global site tag (gtag.js) - Google Analytics