java 设计模式之观察者模式 PropertyChangeSupport

观察者模式其实是比较常用的一种通知模式,即当一个类的属性发生变化要通知其它不等个数的类的时候,常采用这种模式。

在这里我们以java中的Swing中控件间通知为例,也可用于子控件向父控件的变更提示,有点类化于.Net中的委托(delegate).

在观察者模式中,有两个概念:监听者和被监听者,被监听者就是被通知改变的一方,而监听者就是改变通知的一方

比如我们要实现一个自定义的DIalog

里面有两个控件,如下图


上述的对话框中有两个控件,一个jOptionPanel 一个Jlabel,

在这里我们要实现的是在点击JOptionPanel中的确定按钮时,能在下述的label中显示上面的值。

public class TestDialog extends Dialog implents PropertyChangeListener{
 private JOptionPanel jOptionPane;
private JTextField jTextField;
private String btnName="确定";
private JLabel jLabel;
 public TestDialog(){
   Object[] array={jTextField};
    Object[] options={btnName};
    jOptionPane=new JOptionPane(array,JOptionPane.QUESTION_MESSAGE,JOptionPane.YES_NO_OPTION,null,options,options[0]);
        jLabel=new JLable("您在上控件中输入的值为:");
        jOptionPanel.addPropertyChangeListener(this);
}
@Override
public void propertyChange(PropertyChangeEvent e) {
         String prop = e.getPropertyName();


       if (isVisible()
        && (e.getSource() == jOptionPane)
        && (JOptionPane.VALUE_PROPERTY.equals(prop) ||
            JOptionPane.INPUT_VALUE_PROPERTY.equals(prop))){
                   jLabel.setText("您在上控件中输入的值为:"+jTextField.getText());
            }
}
}


在这里子控件中有注册事件发生就会通知父控件,并做出想应的改动。保证消息的传递可靠。同样的只要注册的控件,在其数据发生变化都会被通知到。

可能有人会问这个和定义一个回调函数有什么区别,我觉得最大的区别在于,这种方法更加灵活,比如某些时候,一个控件有什么状态变化,如果分别写回调函数的话要很多,而通过该机制, 我们只要自定义命名一个key,然后当其状态变化时,会及时通知注册了的通过propertyChange的evt.getPropertyName()过滤更改。

下面来看一个完整的“委拖”机制的实现。

public class Student
{

    public String name;
    public  Student(String name){
     this.name=name;
  }
}

public class StuA extends Student{
   private Student obserStu;
  public StuA(Student obserStu){
     super("张三");
       this.obserStu=obserStu;
   obserStu.addChangeListener(propertyChangeListener);
  }
  public void stopSleep(){
     System.out.println("老师来来,停止睡觉!");
  }
	private PropertyChangeListener propertyChangeListener=new PropertyChangeListener() {
			
			
			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				// TODO Auto-generated method stub
				if(evt.getPropertyName().equals("teacher")){
					stopSleep();
				}
			}
		};
}
public class StuB extends Student{
  private Student obserStu;
  public StuA(Student obserStu){
     super("张三");
    this.obserStu=obserStu;
   obserStu.addChangeListener(propertyChangeListener);
  }
  public void stopPlayGame(){
     System.out.println("老师来来,停止游戏!");
  }
	private PropertyChangeListener propertyChangeListener=new PropertyChangeListener() {
			
			
			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				// TODO Auto-generated method stub
				if(evt.getPropertyName().equals("teacher")){
					stopPlayGame();
				}
			}
		};
}
public class StuC extends Student{
  PropertyChangeSupport propertyChangeSupport=new PropertyChangeSupport(this);
  public StuA(){
     super("观察者:王五");
  }
  public void watchTeacher(){
   propertyChangeSupport.firePropertyChange("teacher", "go", "stop");
  }
public void addChangeListener(PropertyChangeListener propertyChangeListener){
			propertyChangeSupport.addPropertyChangeListener(propertyChangeListener);
		}
		public void removeChangeListener(PropertyChangeListener propertyChangeListener){
			propertyChangeSupport.removePropertyChangeListener(propertyChangeListener);
		}
}
public class Test{
   public static void main(String[] arsgs){
   StuC obserStu=new StuC();
    Student stuA=new StuA(obserStu);
   Student stuB=new StuB(obserStu);
   obserStu.watchTeacher();
}
}

不仅观察可以观察老师,甚至是教导主任,家长。。等等,都可以通过PropertyName来区分方法,只要在监听器中加以简单的判断即可,而不用为每一个通知变化都写一个Listener.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值