从Java类库看设计模式Word文档下载推荐.docx

上传人:b****6 文档编号:20065205 上传时间:2023-01-16 格式:DOCX 页数:35 大小:162.24KB
下载 相关 举报
从Java类库看设计模式Word文档下载推荐.docx_第1页
第1页 / 共35页
从Java类库看设计模式Word文档下载推荐.docx_第2页
第2页 / 共35页
从Java类库看设计模式Word文档下载推荐.docx_第3页
第3页 / 共35页
从Java类库看设计模式Word文档下载推荐.docx_第4页
第4页 / 共35页
从Java类库看设计模式Word文档下载推荐.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

从Java类库看设计模式Word文档下载推荐.docx

《从Java类库看设计模式Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《从Java类库看设计模式Word文档下载推荐.docx(35页珍藏版)》请在冰豆网上搜索。

从Java类库看设计模式Word文档下载推荐.docx

当然,这也减少了一定的灵活性。

下面列出了Observer和Observeral的函数列表,及其简单的功能说明

java.util.Observer:

publicvoidupdate(Observableobs,Objectobj)

java.util.Observer接口很简单,只定义了这一个方法,狭义的按照Observer模式的说法,Observer应该在这个方法中调用Subject的getXXX()方法来取得最新的状态,而实际上,你可以只是在其中对Subject的某些事件进行响应。

这便是Java中的代理事件模型的一个雏形--对事件进行响应。

只不过,在Observer模式中将事件特定化为某个状态/数据的改变了。

java.util.Observable

publicvoidaddObserver(Observerobs)

向Subject注册一个Observer。

也就是把这个Observer对象添加到了一个java.util.Observable内部的列表中。

在JDK中对于这个列表是简单的通过一个java.util.Vector类来实现的,而实际上,在一些复杂的Observer模式的应用中,需要把这个部分单另出来形成一个Manager类,来管理Subject和Observer之间的映射。

这样,Subject和Observer进一步的被解藕,程序也会具有更大的灵活性。

publicvoiddeleteObserver(Observerobs)

从Subject中删除一个已注册了Observer的引用。

publicvoiddeleteObservers()

从Subjec中删除所有注册的Observer的引用。

publicintcountObservers()

返回注册在Subject中的Observer个数。

protectedvoidsetChanged()

设置一个内部的标志以指明这个Ovserver的状态已经发生改变。

注意这是一个protected方法,也就是说只能在Observer类和其子类中被调用,而在其它的类中是看不到这个方法的。

protectedvoidclearChanged()

清除上叙的内部标志。

它在notifyObservers()方法内部被自动的调用,以指明Subject的状态的改变已经传递到Ovserver中了。

publicbooleanhasChanged()

确定Subject的状态是否发生了改变。

publicvoidnotifyObservers(Objectobj)

它首先检查那个内部的标志,以判断状态是否改变,如果是的话,它会调用注册在Subject中的每个Observer的update()方法。

在JDK中这个方法内部是作为synchronized来实现的,也就是如果发生多个线程同时争用一个java.util.Observerable的notifyObservers()方法的话,他们必须按调度的等待着顺序执行。

在某些特殊的情况下,这会有一些潜在的问题:

可能在等待的过程中,一个刚刚被加入的Observer会被遗漏没有被通知到,而一个刚刚被删除了的Observer会仍然收到它已经不想要了的通知。

publicvoidnotifyObservers()

等价于调用了notifyObservers(null)。

因而在Java中应用Observer就很简单了,需要做的是:

让需要被观察的Subject对象继承java.util.Observerable,让需要观察的对象实现java.util.Observer接口,然后用java.util.Observerable的addObserver(Observerobj)方法把Observer注册到Subject对象中。

这已经完成了大部分的工作了。

然后调用java.util.Observerable的notifyObservers(Objectarg)等方法,就可以实现Observer模式的机理。

我们来看一个简单使用了这个模式的例子。

这个例子有三个类:

FrameSubject,DateSubject,FrameObject和EntryClass,FrameSubject中用户可以设置被观察的值,然后自动的会在FrameObject中显示出来,DateSubject封装被观察的值,并且充当Observer模式中的Subject。

 

1publicclassFrameSubjectextendsJFrame{

2

3  …………..

4

5  //因为无法使用多重继承,这儿就只能使用对象组合的方式来引入一个

6

7  //java.util.Observerable对象了。

8

9  DateSubjectsubject=newDateSubject();

10

11  //这个方法转发添加Observer消息到DateSubject。

12

13  publicvoidregisterObserver(java.util.Observero){

14

15  subject.addObserver(o);

16

17  }

18

19  //数据改变,事件被触发后调用notifyObservers()来通知Observer。

20

21  voidjButton1_actionPerformed(ActionEvente){

22

23  subject.setWidthInfo(Integer.parseInt(jTextField1.getText()));

24

25  subject.setHeightInfo(Integer.parseInt(jTextField2.getText()));

26

27  subject.notifyObservers();

28

29  }

30

31  ……………

32

33  }

34

35  publicclassDateSubjectextendsObservable{

36

37  //封装被观察的数据

38

39  privateintwidthInfo;

40

41  privateintheightInfo;

42

43  publicintgetWidthInfo(){

44

45  returnwidthInfo;

46

47  }

48

49  publicvoidsetWidthInfo(intwidthInfo){

50

51  this.widthInfo=widthInfo;

52

53  //数据改变后,setChanged()必须被调用,否则notifyObservers()方法会不起作用

54

55  this.setChanged();

56

57  }

58

59  publicvoidsetHeightInfo(intheightInfo){

60

61  this.heightInfo=heightInfo;

62

63  this.setChanged();

64

65  }

66

67  publicintgetHeightInfo(){

68

69  returnheightInfo;

70

71  }

72

73  }

74

75  publicclassFrameObserverextendsJFrameimplementsjava.util.Observer{

76

77  …………..

78

79  //观察的数据

80

81  intwidthInfo=0;

82

83  intheightInfo=0;

84

85  //在update()方法中实现对数据的更新和其它必要的反应。

86

87  publicvoidupdate(Observableo,Objectarg){

88

89  DateSubjectsubject=(DateSubject)o;

90

91  widthInfo=subject.getWidthInfo();

92

93  heightInfo=subject.getHeightInfo();

94

95  jLabel1.setText("

TheheightInfofromsubjectis:

"

);

96

97  jLabel3.setText(String.valueOf(heightInfo));

98

99  jLabel2.setText("

ThewidthInfofromsubjectis:

100

101  jLabel4.setText(String.valueOf(widthInfo));

102

103  }

104

105  …………….

106

107  }

108

109  publicclassEntryClass{

110

111  publicstaticvoidmain(String[]args){

112

113  ……………..

114

115  FrameSubjectframe=newFrameSubject();

116

117  FrameObserverframe2=newFrameObserver();

118

119  //在Subject中注册Observer,将两者联系在一起

120

121  frame.registerObserver(frame2);

122

123  …………..

124

125  frame.setVisible(true);

126

127  frame2.setVisible(true);

128

129  ……………..

130

131  }

132

133  }

134

135

我认为在JDK中这个Observer模式的实现,对于一般的Observer模式的应用,已经是非常的足够了的。

但是一方面它用一个类来实现了Subject,另一方面它使用Vector来保存Subject对于Observer的引用,这虽然简化了编程的过程,但会限制它在一些需要更为灵活,复杂的设计中的应用,有时候(虽然这种情况不多),我们还不得不重新编写新的Subject对象和额外的Manager对象来实现更为复杂的Observer模式的应用。

随着现代软件工业的不断进步,软件系统的规模的日益扩大,越来越需要对某些个不断出现的问题进行模式化思维,以成功的经验或者失败的教训来减少软件开发失败的风险。

模式代表了一种文档化的经验,它为某一类的问题提供了最好(或者说很好)的解决方案,使得即使不是经验丰富的软件工程师,也能够根据模式来构建相对成功的系统。

本节给出的一个Obverser模式的示例,比较好的说明了这一点。

Obverser模式主要解决在对象间的状态映射或者镜像的问题。

在设计一般用途的软件的时候,在C或者C++语言中,用的很多的一个技巧就是回调函数(Callback),所谓的回调函数,意指先在系统的某个地方对函数进行注册,让系统知道这个函数的存在,然后在以后,当某个事件发生时,再调用这个函数对事件进行响应。

在C或者C++中,实现的回调函数方法是使用函数指针。

但是在Java中,并不支持指针,因而就有了Command模式,这一回调机制的面向对象版本。

Command模式用来封装一个命令/请求,简单的说,一个Command对象中包含了待执行的一个动作(语句)序列,以执行特定的任务。

当然,并不是随便怎么样的语句序列都可以构成一个Command对象的,按照Command模式的设计,Command对象和它的调用者Incvoker之间应该具有接口约定的。

也就是说,Invoker得到Command对象的引用,并调用其中定义好的方法,而当Command对象改变(或者是对象本身代码改变,或者干脆完全另外的一个Command对象)之后,Invoker中的代码可以不用更改。

这样,通过封装请求,可以把任务和任务的实现加以分离。

图二:

Command模式的类图

而对于请求的处理又有两种不同的方法,一种是Command只充当代理,将请求转发给某个接受者对象,还有一种是Command对象自己处理完所有的请求操作。

当然,这只是两个极端,更多的情况是Command完成一部分的工作,而另外的一部分这则交给接受者对象来处理。

在新的JDK的代理事件模型中,就可以看作是这样的一个Command模式。

在那个模型中,一个事件监听者类EventListener监听某个事件,并根据接口定义,实现特定的操作。

比如,当用Document对象的addDocumentListener(DocumentListenerlistener)方法注册了一个DocumentListener后,以后如果在Document对象中发生文本插入的事件,DocumentListener中实现的insertUpdate(DocumentEvente)方法就会被调用,如果发生文本删除事件,removeUpdate(DocumentEvente)方法就会被调用。

怎么样,想想看,这是不是一个Command模式的应用呢?

然而,最经典的Command模式的应用,莫过于Swing中的Action接口。

Action实际上继承的是ActionListener,也就是说,它也是一个事件监听者(EventListener)。

但是Action作为一种ActionListener的扩展机制,提供了更多的功能。

它可以在其中包含对这个Action动作的一个或者多个文字的或图标的描叙,它提供了Enable/Disable的功能许可性标志。

并且,一个Action对象可以被多个Invoker,比如实现相同功能的按钮,菜单,快捷方式所共享。

而这些Invoker都知道如何加入一个Action,并充分利用它所提供的扩展机制。

可以说,在这儿Action更像一个对象了,因为它不仅仅提供了对方法的实现,更提供了对方法的描叙和控制。

可以方便的描叙任何的事务,这更是面向对象方法的威力所在。

下面我们看一个Command模式的应用的例子。

假设要实现这样的一个任务:

TaskSchedule。

也就是说,我想对多个任务进行安排,比如扫描磁盘,我希望它每1个小时进行一次,而备份数据,我希望它半个小时进行一次,等等等等。

但是,我并不希望作为TaskSchedule的类知道各个任务的细节内容,TaskSchedule应该只是知道Task本身,而对具体的实现任务的细节并不理会。

因而在这儿,我们就需要对TaskSchedule和Task进行解耦,将任务和具体的实现分离出来,这不正是Command模式的用武之地吗?

图三:

Command模式的应用例子

程序清单:

1//抽象的Task接口,作为回调的Command模式的主体

2publicinterfaceTask{

publicvoidtaskPerform();

4}

5//具体的实现了Task接口的子类,实现特定的操作。

6publicclassBackupTaskimplementsTask{

publicvoidtaskPerform(){

System.out.println("

BackupTaskhasbeenperformed"

}

10}

11//具体的实现了Task接口的子类,实现特定的操作。

12publicclassScanDiskTaskimplementsTask{

13 

14 

ScanDiskTaskhasbeenperformed"

15 

16}

17//一个封装了Task的一个封装类,提供了一些与Task相关的内容,也可以把这些内容

18//这儿不过为了突出Command模式而把它单另出来,实际上可以和Task合并。

19publicclassTaskEntry{

20 

privateTasktask;

21 

privatelongtimeInterval;

22 

privatelongtimeLastDone;

23 

publicTaskgetTask(){

24 

returntask;

25 

26 

publicvoidsetTask(Tasktask){

27 

this.task=task;

28 

29 

publicvoidsetTimeInterval(longtimeInterval){

30 

this.timeInterval=timeInterval;

31 

32 

publiclonggetTimeInterval(){

33 

returntimeInterval;

34 

35 

publiclonggetTimeLastDone(){

36 

returntimeLastDone;

37 

38 

publicvoidsetTimeLastDone(longtimeLastDone){

39 

this.timeLastDone=timeLastDone;

40 

41 

publicTaskEntry(Tasktask,longtimeInteral){

42 

this.task=task;

43 

this.timeInterval=timeInteral;

44 

45}

46//调度管理Task的类,继承Thread只是为了调用其sleep()方法,

47//实际上,如果真的作Task调度的话,每个Task显然应该用单独的Thread来实现。

48publicclassTaskScheduleextendsjava.lang.Thread{

49 

privatejava.util.VectortaskList=newjava.util.Vector();

50 

privatelongsleeptime=10000000000l;

//最短睡眠时间

51 

publicvoidaddTask(TaskEntrytaskEntry){

52 

taskList.add(taskEntry);

53 

taskEntry.setTimeLastDone(System.currentTimeMillis());

54 

if(sleeptime>

taskEntry.getTimeInterval())

55 

sleeptime=taskEntry.getTimeInterval();

56 

57 

//执行任务调度

58 

publicvoidschedulePermorm(){

59 

try{

60 

sleep(sleeptime);

61 

Enumeratione=taskList.elements();

62 

while(e.hasMoreElements()){

63 

TaskEntryte=(TaskEntry)e.nextElement();

64 

if(te.getTimeInterval()+te.getTimeLastDone()

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 行政公文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1