前言
一直很少动手写文档,觉得自己只是一个新手,对很多技术点或者概念理解的不透彻,没多少自信。二来,做程序遇到困难时,在论坛上找到的几乎都是通篇的代码,只能一行行解读代码,自己自圆其说。我不太喜欢这种模式,但是又不知道如何找到详细的资料,天天百度,费力不讨好。在图书馆找参考书,大多都是些基础的东西,也没什么帮助。
昨天,老师布置了一些作业,问我们应不应该强制?回来后我想了想,还是觉得不该强制,如果你爱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
分享到:
相关推荐
观察者模式是设计模式中的一种行为模式,它在Java编程中有着广泛的应用。该模式的主要目的是定义对象...在实际开发中,理解并合理运用观察者模式,能够有效地实现对象之间的交互和通信,提升代码的灵活性和可维护性。
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现发布-订阅...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现事件驱动或者发布...
本篇文章将深入探讨Qt中的观察者模式(Observer Pattern),这是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 观察者模式的核心...
观察者模式,也被称为发布-订阅(Publish-Subscribe)模式,是软件设计中的一种行为模式。...无论是使用Apple提供的API还是自定义实现,理解并熟练运用观察者模式都能提升你的编程技能和项目质量。
观察者模式(Observer Pattern)是设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式常用于实现事件驱动的系统或者...
观察者模式(Observer Pattern)是行为设计模式的一种,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 观察者模式的核心思想是发布-订阅模型,其中...
通过学习观察者模式,你不仅可以提高代码的可维护性和可扩展性,还能更好地理解和利用面向对象设计的原则,如开闭原则(对扩展开放,对修改关闭)。此外,了解并熟练运用观察者模式还有助于你理解和使用其他设计模式...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于事件驱动的系统或者...
.edx和.pdf文件可能包含了这些图形的详细表示,对于深入理解观察者模式的结构和作用非常有帮助。 总的来说,观察者模式是一种强大的设计模式,能够有效地管理对象间的通信,提高系统的灵活性和可扩展性。在实际开发...
在Java编程领域,设计模式是解决常见问题的模板或最佳实践。在这个名为“运用MVC模式及观察者模式的java小程序”的项目中,我们重点探讨了两种经典的...分析和学习这些代码将有助于深入理解MVC和观察者模式的实际应用。
观察者模式,也被称为发布-订阅(Publish-Subscribe)模式,是软件设计模式中的行为模式之一,主要用于对象间的一...理解并熟练运用观察者模式,可以提升代码的可维护性和复用性,使得程序设计更加符合面向对象的原则。
观察者模式(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...
观察者模式(Observer Pattern)是设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式常用于实现事件驱动的系统,...