《重构》之Duplicate Observed Data示例,使用Observer模式实现界面与数据分离

1、说明

利用观察者模式实现JFrame界面与数据分离解耦

2、代码

package com.hallo.refactoring.DOD;

import java.util.Observable;

import io.netty.util.internal.StringUtil;

/**
 * 负责界面修改数据获取、重新计算(length = end - start)
 * @author xwc
 *
 */
public class Interval extends Observable {

	private String _start = "0";
	private String _end = "0";
	private String _length = "0";
	
	String getStart() {
		return _start;
	}
	
	String getEnd() {
		return _end;
	}
	
	String getLength() {
		return _length;
	}
	
	void setStart(String start) {
		_start = _returnZeroIfNullOrEmpty(start);
		_caculateAndSetLength();
		
		setChanged();
		notifyObservers();
	}
	
	void setEnd(String end) {
		_end = _returnZeroIfNullOrEmpty(end);
		_caculateAndSetLength();
		
		setChanged();
		notifyObservers();
	}
	
	void setLength(String length) {
		_length = _returnZeroIfNullOrEmpty(length);
		_caculateAndSetEnd();
		
		setChanged();
		notifyObservers();
	}
	

	private String _returnZeroIfNullOrEmpty(String in) {
		if (StringUtil.isNullOrEmpty(in)) {
			return "0";
		}
		return in;
	}

	private void _caculateAndSetEnd() {
		_end = String.valueOf(Integer.valueOf(_start) + Integer.valueOf(_length));
	}

	private void _caculateAndSetLength() {
		_length = String.valueOf(Integer.valueOf(_end) - Integer.valueOf(_start));
	}
	
}
package com.hallo.refactoring.DOD;

import java.awt.EventQueue;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

/**
 * 负责界面UI修改及回显操作,数据完全来自于Interval
 * @author xwc
 *
 */
public class IntervalWindow extends JFrame implements Observer {

	/**
	 * 
	 */
	private static final long serialVersionUID = -2009756583019733200L;

	private JPanel contentPane;

	TextField startTextField = new TextField();
	TextField endTextField = new TextField();
	TextField lengthTextField = new TextField();
	
	private Interval _subject;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					IntervalWindow frame = new IntervalWindow();
					frame.setTitle("复制被监视数据");
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public IntervalWindow() {
		
		//观察Interval
		_subject = new Interval();
		_subject.addObserver(this);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		/** start **/
		startTextField.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				try {
					_startTextField_FocusLost(e);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		});
		startTextField.setBounds(217, 74, 74, 23);
		contentPane.add(startTextField);

		Label label = new Label("start");
		label.setBounds(120, 74, 69, 23);
		contentPane.add(label);

		/** end **/
		endTextField.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				try {
					_endTextField_FocusLost(e);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		});

		endTextField.setBounds(217, 117, 74, 23);
		contentPane.add(endTextField);

		Label label_1 = new Label("end");
		label_1.setBounds(120, 117, 69, 23);
		contentPane.add(label_1);

		/** length **/
		Label label_2 = new Label("length");
		label_2.setBounds(120, 165, 69, 23);
		contentPane.add(label_2);

		lengthTextField.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				try {
					_lengthTextField_FocusLost(e);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		});
		lengthTextField.setBounds(217, 165, 74, 23);
		contentPane.add(lengthTextField);
		
		//初始化赋值,从Interval类获取
		_subject.setStart(startTextField.getText());
		_subject.setEnd(endTextField.getText());
		_subject.setLength(lengthTextField.getText());
	}

	/**
	 * focusLost事件触发时,将当前值传给Interval,然后通过update回调方法,更新界面3个域值
	 * @param e
	 * @throws Exception
	 */
	protected void _lengthTextField_FocusLost(FocusEvent e) throws Exception {
		_subject.setLength(lengthTextField.getText());
	}

	protected void _endTextField_FocusLost(FocusEvent e) throws Exception {
		_subject.setEnd(endTextField.getText());
	}

	protected void _startTextField_FocusLost(FocusEvent e) throws Exception {
		_subject.setStart(startTextField.getText());
	}

	@Override
	public void update(Observable o, Object arg) {
		startTextField.setText(_subject.getStart());
		endTextField.setText(_subject.getEnd());
		lengthTextField.setText(_subject.getLength());
	}
}

3、效果

修改start或end值时,length值自动修改;修改length值时,end值自动更新:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值