软件体系结构与设计模式 观察者模式范文.docx

上传人:b****4 文档编号:5139068 上传时间:2023-05-08 格式:DOCX 页数:18 大小:61.43KB
下载 相关 举报
软件体系结构与设计模式 观察者模式范文.docx_第1页
第1页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第2页
第2页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第3页
第3页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第4页
第4页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第5页
第5页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第6页
第6页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第7页
第7页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第8页
第8页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第9页
第9页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第10页
第10页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第11页
第11页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第12页
第12页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第13页
第13页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第14页
第14页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第15页
第15页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第16页
第16页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第17页
第17页 / 共18页
软件体系结构与设计模式 观察者模式范文.docx_第18页
第18页 / 共18页
亲,该文档总共18页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

软件体系结构与设计模式 观察者模式范文.docx

《软件体系结构与设计模式 观察者模式范文.docx》由会员分享,可在线阅读,更多相关《软件体系结构与设计模式 观察者模式范文.docx(18页珍藏版)》请在冰点文库上搜索。

软件体系结构与设计模式 观察者模式范文.docx

软件体系结构与设计模式观察者模式范文

观察者模式(别名:

依赖,发布-订阅)

定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都得到通知并被自动更新。

ObserverPattern(AnotherName:

Dependents,Publish-Subscribe)

Defineaone-to-manydependencybetweenobjectssothatwhenoneobjectchangesstate,allitsdependentsarenotifiedandupdatedautomatically..

一、概述

在许多设计中,经常涉及到多个对象都对一个特殊对象中的数据变化感兴趣,而且这多个对象都希望跟踪那个特殊对象中的数据变化。

二、模式的结构与使用

观察者模式的结构中包括四种角色:

•主题(Subject)

•观察者(Observer)

•具体主题(ConcreteSubject)

•具体观察者(ConcreteObserver)

模式的结构的描述与使用

有一个大学毕业生和一个归国留者都希望能及时知道“求职中心”最新的职业需求信息。

1.主题:

Subject.java

publicinterfaceSubject{

publicvoidaddObserver(Observero);

publicvoiddeleteObserver(Observero);

publicvoidnotifyObservers();

}

主题接口规定了具体主题需要实现的添加、删除观察者以及通知观察者更新数据的方法

2.观察者:

Obsever.java

publicinterfaceObserver{

publicvoidhearTelephone(StringheardMess);

}

观察者接口规定了具体观察者用来更新数据的方法。

3.具体主题SeekJobCenter.java_1

publicclassSeekJobCenterimplementsSubject{

Stringmess;

booleanchanged;

ArrayListpersonList;

SeekJobCenter(){

personList=newArrayList();

mess="";

changed=false;

}

publicvoidaddObserver(Observero){

if(!

(personList.contains(o)))

personList.add(o);}

publicvoiddeleteObserver(Observero){

if(personList.contains(o))

personList.remove(o);

}

3.具体主题SeekJobCenter.java_2

publicvoidnotifyObservers(){

if(changed){

for(inti=0;i

Observerobserver=personList.get(i);

observer.hearTelephone(mess);}

changed=false;

}

}

publicvoidgiveNewMess(Stringstr){

if(str.equals(mess))

changed=false;

else{

mess=str;

changed=true;

}

}

}

具体主题通过实现notifyObservers()方法来通知具体观察者,实现的方式是遍历具体主题中用来存放观察者引用的集合,并让集合中的每个具体观察者执行观察者接口规定更新数据的方法。

4.具体观察者_1UniversityStudent.java

publicclassUniverStudentimplementsObserver{

Subjectsubject;

FilemyFile;

UniverStudent(Subjectsubject,StringfileName){

this.subject=subject;

subject.addObserver(this);

myFile=newFile(fileName);

}

publicvoidhearTelephone(StringheardMess){

try{RandomAccessFileout=newRandomAccessFile(myFile,"rw");

out.seek(out.length());

byte[]b=heardMess.getBytes();

out.write(b);

System.out.print("我是一个大学生,");

System.out.println("我向文件"+myFile.getName()+"写入如下内容:

");

System.out.println(heardMess);

}

catch(IOExceptionexp){System.out.println(exp.toString());}

}

}

4.具体观察者_2HaiGui.java

publicclassHaiGuiimplementsObserver{

Subjectsubject;

FilemyFile;

HaiGui(Subjectsubject,StringfileName){

this.subject=subject;

subject.addObserver(this);

myFile=newFile(fileName);

}

publicvoidhearTelephone(StringheardMess){

try{booleanboo=heardMess.contains("java程序员");

if(boo){

RandomAccessFileout=newRandomAccessFile(myFile,"rw");

out.seek(out.length());

byte[]b=heardMess.getBytes();

out.write(b);

System.out.print("我是一个海归,");

System.out.println("我向文件"+myFile.getName()+"写入如下内容:

");

System.out.println(heardMess);

}

else{

System.out.println("我是海归,这次的信息中没有我需要的信息");}

}

catch(IOExceptionexp){System.out.println(exp.toString());}

}

}

5.应用Application.java

publicclassApplication{

publicstaticvoidmain(Stringargs[]){

SeekJobCentercenter=newSeekJobCenter();

UniverStudentzhangLin=newUniverStudent(center,"A.txt");

HaiGuiwangHao=newHaiGui(center,"B.txt");

center.giveNewMess("腾辉公司需要10个java程序员。

");

center.notifyObservers();

center.giveNewMess("海景公司需要8个动画设计师。

");

center.notifyObservers();

center.giveNewMess("仁海公司需要9个电工。

");

center.notifyObservers();

center.giveNewMess("仁海公司需要9个电工。

");

center.notifyObservers();

}

三、“推”数据与“拉”数据

•推数据方式是指具体主题将变化后的数据全部交给具体观察者。

–具体主题认为具体观察者需要这些变化后的全部数据

•拉数据方式是指具体主体提供了获得变化后数据的方法,具体观察者调用这些方法获得变化后的数据。

–具体主题不知道具体观察者是否需要这些变化后的数据行为协作

四、观察者模式的优点

•具体主题和具体观察者是松耦合关系。

由于主题(Subject)接口仅仅依赖于观察者(Observer)接口,因此具体主题只是知道它的观察者是实现观察者(Observer)接口的某个类的实例,但不需要知道具体是哪个类。

同样,由于观察者仅仅依赖于主题(Subject)接口,因此具体观察者只是知道它依赖的主题是实现主题(subject)接口的某个类的实例,但不需要知道具体是哪个类。

•观察模式满足“开-闭原则”。

主题(Subject)接口仅仅依赖于观察者(Observer)接口,这样,我们就可以让创建具体主题的类也仅仅是依赖于观察者(Observer)接口,因此如果增加新的实现观察者(Observer)接口的类,不必修改创建具体主题的类的代码。

同样,创建具体观察者的类仅仅依赖于主题(Observer)接口,如果增加新的实现主题(Subject)接口的类,也不必修改创建具体观察者类的代码。

五、应用举例

•老师有电话号码,学生需要知道老师的电话号码以便于在合时的时候拨打,在这样的组合中,老师就是一个被观察者(Subject),学生就是需要知道信息的观察者,当老师的电话号码发生改变时,学生得到通知,并更新相应的电话记录

publicinterfaceSubject{

publicvoidattach(Observero);

publicvoiddetach(Observero);

publicvoidnotice();

}

packageobserver;

publicinterfaceObserver{

publicvoidupdate();

}

publicclassTeacherimplementsSubject{

privateStringphone;

privateVectorstudents;

publicTeacher(){

phone="";

students=newVector();

}

publicvoidattach(Observero){

students.add(o);

}

publicvoiddetach(Observero){

students.remove(o);

}

publicvoidnotice(){

for(inti=0;i

((Observer)students.get(i)).update();

}

publicvoidsetPhone(Stringphone){

this.phone=phone;

notice();

}

publicStringgetPhone(){

returnphone;

}

}

publicclassStudentimplementsObserver{

privateStringname;

privateStringphone;

privateTeacherteacher;

publicStudent(Stringname,Teachert){

this.name=name;

teacher=t;

}

publicvoidshow(){

System.out.println("Name:

"+name+"\nTeacher'sphone:

"+phone);

}

publicvoidupdate(){

phone=teacher.getPhone();

}

}

publicclassClient{

publicstaticvoidmain(String[]args){

Vectorstudents=newVector();

Teachert=newTeacher();

for(inti=0;i<10;i++){

Studentst=newStudent("lili"+i,t);

students.add(st);

t.attach(st);

}

t.setPhone("");

for(inti=0;i<10;i++)

((Student)students.get(i)).show();

t.setPhone("");

for(inti=0;i<10;i++)

((Student)students.get(i)).show();

}

}

第七章策略模式

策略模式(别名:

政策)

定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。

本模式使得算法可独立于使用它的客户而变化。

StrategyPattern(AnotherName:

Policy)

Defineafamilyofalgorithms,encapsulateeachone,andmaketheminterchangeable.Strategyletsthealgorithmvaryindependentlyfromclientsthatuseit.

一、概述

策略模式是处理算法的不同变体的一种成熟模式,策略模式通过接口或抽象类封装算法的标识,即在接口中定义一个抽象方法,实现该接口的类将实现接口中的抽象方法。

在策略模式中,封装算法标识的接口称作策略,实现该接口的类称作具体

二、策略模式的结构与使用

策略模式的结构中包括三种角色:

•策略(Strategy)

•具体策略(ConcreteStrategy)

•上下文(Context)

•策略模式的UML类图

策略模式的结构的描述与使用

在某种比赛中有若干个裁判,每位裁判给选手一个得分。

选手的最后得分是根据全体裁判的得分计算出来的。

请给出几种计算选手得分的评分方案,对于某次比赛,可以从你的方案中选择一种方案作为本次比赛的评分方案。

•1.策略(Strategy):

Computable.java

publicinterfaceComputableStrategy{

publicabstractdoublecomputeScore(double[]a);

}

2.具体策略(ConcreteStrategy):

StrategyOne.java

(代数平均值方法)

publicclassStrategyOneimplementsComputableStrategy{

publicdoublecomputeScore(double[]a){

doublescore=0,sum=0;

for(inti=0;i

sum=sum+a[i];

}

score=sum/a.length;

returnscore;

}

}

2.具体策略(ConcreteStrategy):

StrategyTwo.java

(去掉最大值和最小值,然后计算代数平均值)

importjava.util.Arrays;

publicclassStrategyTwoimplementsComputableStrategy{

publicdoublecomputeScore(double[]a){

if(a.length<=2)

return0;

doublescore=0,sum=0;

Arrays.sort(a);

for(inti=1;i

sum=sum+a[i];

}

score=sum/(a.length-2);

returnscore;

}

}

3.上下文:

GymnasticsGame.java

publicclassGymnasticsGame{

ComputableStrategystrategy;

publicvoidsetStrategy(ComputableStrategystrategy){

this.strategy=strategy;

}

publicdoublegetPersonScore(double[]a){

if(strategy!

=null)

returnputeScore(a);

else

return0;

}

}

4.应用:

Application.java_1

publicclassApplication{

publicstaticvoidmain(Stringargs[]){

GymnasticsGamegame=newGymnasticsGame();

game.setStrategy(newStrategyOne());

Personzhang=newPerson();

zhang.setName("张三");

double[]a={9.12,9.25,8.87,9.99,6.99,7.88};

Personli=newPerson();

li.setName("李四");

double[]b={9.15,9.26,8.97,9.89,6.97,7.89};

zhang.setScore(game.getPersonScore(a));

li.setScore(game.getPersonScore(b));

System.out.println("使用算术平均值方案:

");

System.out.println("得分:

",zhang.getName(),zhang.getScore());

System.out.println("得分:

%5.3f%n",li.getName(),li.getScore());

}

}

4.应用:

Application.java_2

classPerson{

Stringname;

doublescore;

publicvoidsetScore(doublet){

score=t;

}

publicvoidsetName(Strings){

name=s;

}

publicdoublegetScore(){

returnscore;

}

publicStringgetName(){

returnname;

}

}

三、策略模式的优点

•上下文(Context)和具体策略(ConcreteStrategy)是松耦合关系。

因此上下文只知道它要使用某一个实现Strategy接口类的实例,但不需要知道具体是哪一个类。

•策略模式满足“开-闭原则”。

当增加新的具体策略时,不需要修改上下文类的代码,上下文就可以引用新的具体策略的实例。

四、适合使用策略模式的情景

•一个类定义了多种行为,并且这些行为在这个类中以多个条件语句的形式出现,可以使用策略模式避免在类中使用大量的条件语句。

•程序不需要暴露复杂的、与算法相关的数据结构,可以使用策略模式封装算法。

•需要使用一个算法的不同变体。

•把数组导出为表格的算法,输入一个数组,导出一个表格,当用户想改变导出的表格时,便可以通过改变输出的算法改变输出的结果。

如果输出的内容用以网页显示,则输出

Jack
Maya
Mikes
Shadow

•如果输出的结果用以直接的屏幕输出,则可以输出:

+----+----+-----+------+

|Jack|Maya|Mikes|Shadow|

+----+----+-----+------+

publicinterfaceTableExporter{

publicStringgetExported(String[]data);

}

publicclassHtmlExporterimplementsTableExporter{

publicStringgetExported(String[]data){

if(data==null){

return"";

}

StringBuffersb=newStringBuffer();

sb.append("

");

for(inti=0;i

sb.append("

");

sb.append("

"+data[i]+"
");

returnsb.toString();

}

}

publicclassLineExporterimplementsTableExporter{

publicStringgetExported(String[]data){

if(data==null){

return"";

}

StringBuffertop=newStringBuffer("+");

StringBuffermid=newStringBuffer("|");

for(inti=0;i

Stringstr=data[i];

for(intj=0;j

top.append("-");

mid.append(str);

top.append("+");

mid.append("|");

}

top.append("\n");

mid.append("\n");

returntop.toString()+mid.toString()+top.toString();

}

}

publicclassClie

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

当前位置:首页 > 解决方案 > 工作计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2