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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值