观察者模式举例-统计文本中的单词和数字

设计要求

  1. 设计一个窗口,该窗口中有三个文本区。
  2. 三个文本区域中的其中一个可供用户编辑文本,另外两个用户不可编辑。
  3. 当用户在可编辑的文本中进行编辑时,另外两个不可编辑的文本区中的一个将显示用户所编辑文本中出现的单词,另一个将显示用户所编辑文本中包含的数字。

设计实现

用户所编辑文本应当视作观察者模式中的一个具体主题所维护的数据,而另外两个文本区应该视作是两个具体观察者中的成员。

1.主题

本问题中,使用java.util包中的Observable类作为主题。

2.观察者

观察者是java.util包中的Observer接口。

3.具体主题

InputTextSubject是Observable类的子类,负责创建具体主题。InputTextSubject类包含一个可编辑的JTextArea文本区。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class InputTextSubject extends Observable {
String content;
JTextArea text;
public InputTextSubject() {
text = new JTextArea(10, 15);
text.setLineWrap(true);
text.setWrapStyleWord(true);
(text.getDocument()).addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
content = text.getText();
setChanged();
notifyObservers(content);
}
});
}
public String getContent() {
return content;
}
public JTextArea getText() {
return text;
}
}

4.具体观察者

负责创建具体观察者的类是ShowWord和ShowDigit。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// ShowWord.java
public class ShowWord extends JPanel implements Observer {
Observable subject;
JTextArea text;
TreeSet<String> worldList;
public ShowWord(Observable observable) {
this.subject = observable;
subject.addObserver(this);
text = new JTextArea(10, 15);
text.setLineWrap(true);
text.setWrapStyleWord(true);
text.setEditable(false);
add(new JScrollPane(text));
worldList = new TreeSet<String>();
}
@Override
public void update(Observable subject, Object object) {
text.setText(null);
text.append("出现的单词有(按字典顺序):\n");
worldList.clear();
String content = object.toString();
String regx = "[\\s\\d\\p{Punct}]+";
String words[] = content.split(regx);
for (int i = 0; i < words.length; i++) {
worldList.add(words[i]);
}
Iterator<String> te = worldList.iterator();
while (te.hasNext()) {
text.append(te.next()+" ");
}
}
}

// ShowDigit.java
public class ShowDigit extends JPanel implements Observer {
Observable subject;
JTextArea text;
Vector<String> vector;
public ShowDigit(Observable subject) {
this.subject = subject;
subject.addObserver(this);
text = new JTextArea(10, 15);
text.setLineWrap(true);
text.setWrapStyleWord(true);
text.setEditable(false);
add(new JScrollPane(text));
vector = new Vector<String>();
}
@Override
public void update(Observable subject, Object object) {
text.setText(null);
text.append("出现的数字有:\n");
vector.removeAllElements();
String content = object.toString();
String regex = "\\D+"; //非数字字符构成的正则表达式
String digitWords[] = content.split(regex);
for (int i = 0; i < digitWords.length; i++) {
if (! vector.contains(digitWords[i])) {
vector.add(digitWords[i]);
}
}
for (int i = 0; i < vector.size(); i++) {
text.append(vector.elementAt(i)+" ");
}
}
}

5.测试程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Application extends JFrame {
public Application() {
InputTextSubject textSubject = new InputTextSubject(); //具体主题
ShowWord observerOne = new ShowWord(textSubject); //具体观察者
ShowDigit observerTwo = new ShowDigit(textSubject); //具体观察者
setLayout(new FlowLayout());
add(new JScrollPane(textSubject.getText()) );
add(observerOne);
add(observerTwo);
setBounds(20, 20, 400, 300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[]){
new Application();
}
}

用户在可编辑文本区域输入文本时,另外连个文本区分别显示了用户输入文本中包含的单词以及所包含的数字字符序列,运行效果如图所示。

程序运行效果

欢迎关注我的其它发布渠道