《重构,改善现有代码的设计》第八章 Duplicate Observed Data

Java代码 复制代码 收藏代码
  1. import java.awt.Color;
  2. import java.awt.Container;
  3. import java.awt.FlowLayout;
  4. import java.awt.Label;
  5. import java.awt.TextField;
  6. import java.awt.event.FocusAdapter;
  7. import java.awt.event.FocusEvent;
  8. import java.awt.event.WindowAdapter;
  9. import java.awt.event.WindowEvent;
  10. import java.util.Observable;
  11. import java.util.Observer;
  12. import javax.swing.JFrame;
  13. /**
  14. * 《重构,改善现有代码的设计》第八章 Duplicate Observed Data
  15. *
  16. * 业务逻辑:
  17. * 一个JFrame(类IntervalWindow)有三个TextField,分别是start,end和length
  18. * 如果你修改Start或End,length就会自动成为两者计算所得的长度
  19. * 如果你修改length,End就会随之改变(start不变)
  20. *
  21. * 主要是使用了Observer模式:
  22. * start,end和length之间的运算,是与具体界面无关的,应该独立出来(成为一个Subject,观察者模式里面的“目标”)
  23. *
  24. * 关键在于解决以下两个问题:
  25. * 1.什么时候计算?当界面上的TextField值有变动时,由WindowObserver调用Subject的set方法
  26. * 2.计算后如何通知界面?Subject调用notifyObservers方法,这个方法会触发WindowObserver的update方法
  27. *
  28. */
  29. public class ObserveGUIWindow {
  30. public static void main(String[] args) {
  31. new WindowObserver().init();
  32. }
  33. }
  34. class WindowObserver implements Observer {
  35. private TextField startField;
  36. private TextField endField;
  37. private TextField lengthField;
  38. private Subject subject;
  39. public void init() {
  40. JFrame f = new JFrame("This is a test");
  41. f.setSize(200, 200);
  42. Container content = f.getContentPane();
  43. content.setBackground(Color.white);
  44. content.setLayout(new FlowLayout());
  45. startField = new TextField("0", 10);
  46. endField = new TextField("0", 10);
  47. lengthField = new TextField("0", 10);
  48. SymFocus listener = new SymFocus();
  49. startField.addFocusListener(listener);
  50. endField.addFocusListener(listener);
  51. lengthField.addFocusListener(listener);
  52. Label startLabel = new Label("start:");
  53. Label endLabel = new Label("end:");
  54. Label lengthLabel = new Label("length:");
  55. content.add(startLabel);
  56. content.add(startField);
  57. content.add(endLabel);
  58. content.add(endField);
  59. content.add(lengthLabel);
  60. content.add(lengthField);
  61. f.setLocationRelativeTo(null);
  62. f.setVisible(true);
  63. f.addWindowListener(new WindowAdapter() {
  64. public void windowClosing(WindowEvent e) {
  65. System.exit(0);
  66. }
  67. });
  68. subject = new Subject();
  69. subject.addObserver(this);
  70. }
  71. //更新界面,最新的值(计算后)来自Subject
  72. public void update(Observable o, Object arg) {
  73. Subject subject = (Subject)o;
  74. startField.setText(subject.getStart());
  75. endField.setText(subject.getEnd());
  76. lengthField.setText(subject.getLength());
  77. }
  78. class SymFocus extends FocusAdapter {
  79. public void focusLost(FocusEvent event) {
  80. Object object = event.getSource();
  81. if (object == startField)
  82. StartFieldFocusLost(event);
  83. else if (object == endField)
  84. EndFieldFocusLost(event);
  85. else if (object == lengthField)
  86. LengthFieldFocusLost(event);
  87. }
  88. }
  89. void StartFieldFocusLost(FocusEvent event) {
  90. //从界面取得输入的值
  91. String start = startField.getText();
  92. subject.setStart(isInteger(start) ? start : "0");
  93. //交由Subject计算
  94. subject.calculateLength();
  95. }
  96. void EndFieldFocusLost(FocusEvent event) {
  97. String end = endField.getText();
  98. subject.setEnd(isInteger(end) ? end : "0");
  99. subject.calculateLength();
  100. }
  101. void LengthFieldFocusLost(FocusEvent event) {
  102. String length = lengthField.getText();
  103. subject.setLength(isInteger(length) ? length : "0");
  104. subject.calculateEnd();
  105. }
  106. boolean isInteger(String str) {
  107. return str != null && str.matches("[0-9]+");
  108. }
  109. }   
原文地址:https://www.cnblogs.com/bjanzhuo/p/3575895.html