《软件体系结构》实验:软件体系结构风格之应用一、实验目的通过KWIC 实例分析,理解和掌握软件体系结构风格设计与实现。
二、实验容多种软件风格设计与实现之KWIC 实例:1.采用主/子程序体系结构风格实现KWIC 关键词索引系统2.采用面向对象体系架构风格实现KWIC 关键词索引系统 3.采用管道过滤体系架构风格实现KWIC 关键词索引系统4.采用事件过程调用体系架构风格实现KWIC 关键词索引系统三、实验要求与实验环境熟练掌握基于主/子程序体系结构风格的KWIC 关键词索引系统,在此基础上,完成基于面向对象体系架构风格的KWIC 关键词索引系统设计与实现。
选做基于管道过滤体系架构风格的KWIC 关键词索引系统;选做基于事件过程调用体系架构风格的KWIC 关键词索引系统。
实验课前完成实验报告的实验目的、实验环境、实验容、实验操作过程等容;实验课中独立/团队操作完成实验报告的实验操作、实验结果及结论等容;每人一台PC 机,所需软件Win2003/XP 、UML 工具(EclipseUML/Rose/Visio/StartUML/)、Eclipse/MyEclipse、JDK6.0 等。
四、实验操作1、采用主/子程序体系结构风格实现KWIC 关键词索引系统主程序/子程序风格(Main Program/Subroutine Style)将系统组织成层次结构,包括一个主程序和一系列子程序。
主程序是系统的控制器,负责调度各子程序的执行。
各子程序又是一个局部的控制器,调度其子程序的执行。
设计词汇表:主程序main(), 子程序 shift(), sort() 方法,方法的调用,返回构件和连接件类型:构件:各类子程序,如shift(),sort()连接件:方法的调用基本的计算模型:子程序有shift(), sort()方法,shift() 对单词进行移位,sort()方法对单词进行排序风格的基本不变性:主程序有顺序地调用子程序,单线程控制。
KWIC 的主/子程序体系结构风格示意图如下所示:主程序/子程序风格的重要设计决策与约束有:●基于声明-使用(程序调用)关系建立连接件,以层次分解的方式建立系统部件,共同组成层次结构。
●每一个上层部件可以“使用”下层部件,但下层部件不能“使用”上层部件,即不允许逆方向调用。
●系统应该是单线程执行。
主程序部件拥有最初的执行控制权,并在“使用”中将控制权转移给下层子程序。
●子程序只能够通过上层转移来获得控制权,可以在执行中将控制权转交给下层的子子程序,并在自身执行完成之后必须将控制权还交给上层部件。
KWIC 主程序/子程序风格的Java 语言实现见附件。
主程序/子程序风格的主要实现机制是模块实现,它将每个子程序都实现为一个模块,主程序实现为整个系统的起始模块。
依照抽象规格的层次关系,实现模块也被组织为相应的层次机构,通过导入/导出关系相连接。
需要强调的是,虽然主程序/子程序风格非常类似于结构化程序的结构,但是主程序/子程序风格是基于部件与连接件建立的高层结构。
它的部件不同于程序,而是更加粗粒度的模块。
而且,在部件的实现模块部,可以使用结构化方法,也可以使用面向对象方法,这并不妨碍整个系统的高层结构符合主程序/子程序风格的约定。
主程序/子程序风格的优点有:流程清晰,易于理解。
强控制性。
严格的层次分解和严格的控制权转移使得主程序/子程序风格对程序的实际执行过程具备很强的控制能力,这带来了一个特点:如果一个子程序所连接的子子程序是正确的,那么就很容易保证该子程序的“正确性”。
所以,主程序/子程序风格比其他常见风格更能控制程序的“正确性”。
2、采用面向对象体系结构风格实现KWIC 关键词索引系统面向对象式风格,需要强调说明的是它的“对象”是部件,属于高层结构的元素,虽然名称相同,但它并不是面向对象方法中所述的“对象”实体。
“面向对象式”风格的命名是因为它借鉴了面向对象方法的思想,而不是因为它使用面向对象方法实现体系结构,这也是在该风格名称中有一个“式”字的原因。
面向对象式风格的主要实现机制是模块实现,它将每个对象部件实例都实现为一个模块。
存在连接的对象部件实例之间会存在模块的导入/导出关系。
每个模块部可以是基于面向对象方法的实现,也可以是基于结构化方法的实现。
设计词汇表:(1)input, output, shift, sort, main 类(2)shift, sort, output 对象(3)对象间的消息传递构件和连接件类型:(1)构件类型:对象(2)连接件的类型:为对象间的消息传递KWIC 的面向对象程序体系结构风格示意图如下所示:基本的计算模型:Input 模块从文本文件input.txt 中一行一行读取单Shift 模块用于将单词移位。
Sort模块将单词进行排序。
Output 模块将最终结果写到文本文件output.txt 中KWIC 面向对象风格的Java 语言实现见附件。
面向对象式风格的优点有:部实现的可修改性。
因为面向对象式风格要求封装部数据,隐藏部实现,所以它可以在不影响外界的情况下,变更其部实现。
易开发、易理解、易复用的结构组织。
面向对象式风格将系统组织为一系列平等、自治的单位,每个单位负责自身的“正确性”,不同单位之间仅仅是通过方法调用相连接,这非常契合模块化思想,能够建立一个易开发、易理解、易复用的实现结构。
3、采用管道和过滤器体系结构风格实现KWIC 关键词索引系统管道-过滤器风格将系统的功能逻辑建立为部件集合。
每个部件实例完成一个对数据流的独立功能处理,它接收数据流输入,进行转换和增量后进行数据流输出。
连接件是管道机制,它将前一个过滤器的数据流输出传递给后一个过滤器作为数据流输入。
连接件也可能会进行数据流的功能处理,进行转换或增量,但连接件进行功能处理的目的为了适配前一个过滤器的输出和后一个过滤器的输入,而不是为了直接承载软件系统的需求。
各个过滤器可以并发执行。
每个过滤器都可以在数据输入不完备的情况下就开始进行处理,每次接到一部分数据流输入就处理和产生一部分输出。
这样,整个的过滤器网络就形成了一条流水线。
设计词汇表:Pipe, Filter构件和连接件类型构件:Filter连接件:Pipe KWIC 的管道过滤器体系结构风格示意图如下所示:基本的计算模型:过滤器读管道输出流,过滤器写管道输入流,过滤器通过对输入流的增量计算来完成风格的基本不变性:过滤器是独立的实体,它们之间通过管道传递数据管道-过滤器风格可以为所有过滤器部件实例建立模块实现,每个过滤器部件实例被实 现为一个单独的模块,可以为所有简单的管道连接件建立一个通用的模块实现,为每个复杂的管道连接件建立一个单独的模块实现,相关联过滤器部件的实现模块要导入管道实现模块。
因为管道-过滤器风格需要并发执行,所以管道-过滤器风格需要为所有过滤器部件实例和复杂连接件实例建立进程实现,每个过滤器部件实例和复杂连接件实例被实现为一个进程。
input output Shifting sorting Input mediumFilter Pipe System I/O如果操作系统能够提供管道机制,那么进程实现时的简单管道可以利用操作系统提供的机制来实现。
此时,所有的实现进程都需要部署在同一个物理节点。
如果有中间件平台能够提供管道机制,那么进程实现时的简单管道可以利用中间件平台提供的机制来实现。
此时,各个实现进程可以被部署在不同的网络节点。
KWIC 基于管道过滤器风格的JAVA 语言实现见附件。
实验结果:输入文件:输出文件:五、实验总结通过本次实验认识到软件体系结构风格是描述某一特定应用领域中系统组织方式的惯用模式。
软件体系结构设计的一个核心问题是能否使用重复的体系结构模式,即能达到体系结构级的软件重用。
也就是说,能否在不同的软件系统中,使用同一体系结构。
主/子程序体系结构风格、面向对象体系架构风格、管道过滤体系架构风格、用事件过程调用体系架构风格是四种常用的软件体系结构风格,对于实现同一种功能的软件可以分别采用以上的这四种风格。
在建立体系结构过程中,不断明确设计词汇表、构建和连接件的类型、可容许的结构模式、基本的计算类型、风格的基本不变形、常用例子、优缺点。
通过明确这些问题,可以理解一种体系结构的基本特征,从而为实现体系结构重用提供可能。
通过对KWIC 进行建模和实现,让我动手把简单的软件体系结构代码实现,在程序里体现体系结构的基本思想,拓展了数据结构的基本知识,将软件设计思想体现在编码环节,为以后的体系结构设计提供基础。
KWIC 主程序/子程序风格的Java 语言实现:public static void alphabetize(){String[] tmpArray = new String[shiftedLineIndexes.size()];shiftedLineIndexes.toArray(tmpArray);Arrays.sort(tmpArray); sortedLineIndexes=tmpArray;}public static void Output(StringoutputAddress){ FileWriter fw = null;try {fw = new FileWriter(outputAddress);} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace(); }BufferedWriter bw=new BufferedWriter(fw);for(inti=0;i<sortedLineIndexes.length;i++){try {bw.write(sortedLineIndexes[i]); bw.newLine();} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace(); }}try {bw.close();} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace(); }}public static void Input(StringiFile){ FileReader fr=null; try{ fr=new FileReader(iFile);} catch (FileNotFoundException e) { e.printStackTrace(); }BufferedReader br=new BufferedReader(fr); textLines=new ArrayList<String>();try { while(br.ready()){textLines.add(br.readLine());}} catch (IOException e) { e.printStackTrace();}}public static voidCircularShift(){ shiftedLineIndexes=newArrayList<String>(); for(inti=0;i<textLines.size();i++){ StringorinLine=textLines.get(i); Stringsarray[]=orinLine.split(" "); for(intj=0;j<sarray.length;j++){ StringnewLine=sarray[j]; if(sarray.length>1){if(j==sarray.length-1){for(int k=0;k<(sarray.length-1);k++){newLine=newLine+" "+sarray[k];}}else{for(int k=j+1;k<sarray.length;k++){newLine=newLine+" "+sarray[k];}for(int m=0;m<j;m++){ newLine=newLine+" "+sarray[m];}}}shiftedLineIndexes.add(newLine);} } }KWIC 面向对象风格的Java 语言实现://InputStore.java importjava.io.BufferedReader; importjava.io.FileNotFoundException; importjava.io.FileReader; importjava.io.IOException; importjava.util.ArrayList; public classInputStore { publicArrayList<String> ls;public InputStore(ArrayList<String> ls){ this.ls=ls; }public void input(StringinputFile){ FileReader fr=null;try {fr=new FileReader(inputFile); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace();}BufferedReader br=new BufferedReader(fr);try { while(br.ready()){ls.add(br.readLine());}} catch (IOException e) { // TODOAuto-generated catch blocke.printStackTrace();}}} //Output.java importjava.io.BufferedWriter; importjava.io.FileWriter; importjava.io.IOException; importjava.util.ArrayList; publicclass Output { publicArrayList<String> ls;public Output(ArrayList<String> ls){ this.ls=ls; }public void output(String outputAddress){FileWriter fw = null; try {fw = new FileWriter(outputAddress);} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}BufferedWriter bw=new BufferedWriter(fw);for(int i=0;i<ls.size();i++){try {bw.write(ls.get(i)); bw.newLine();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}try {bw.close();} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace();}}}//Alphabetizer.java importjava.util.ArrayList; import java.util.Arrays;public class Alphabetizer { publicArrayList<String> ls; publicAlphabetizer(ArrayList<String>ls){ this.ls=ls;}public void alpha(){String[] tmpArray = new String[ls.size()];ls.toArray(tmpArray);Arrays.sort(tmpArray);for(inti=0;i<ls.size();i++){ ls.set(i, tmpArray[i]);}}}//CircularShifter.java importjava.util.ArrayList; public classCircularShifter { public ArrayList<String> ls;public CircularShifter(ArrayList<String>ls){ this.ls=ls;}public void shift(){ArrayList<String> shiftedLineIndexes=new ArrayList<String>(); for(int i=0;i<ls.size();i++){String orinLine=ls.get(i); String sarray[]=orinLine.split(" "); for(int j=0;j<sarray.length;j++){ String newLine=sarray[j];if(sarray.length>1){ if(j==sarray.length-1){ for(intk=0;k<(sarray.length-1);k++){newLine=newLine+" "+sarray[k];}}else{for(int k=j+1;k<sarray.length;k++){newLine=newLine+" "+sarray[k];}for(int m=0;m<j;m++){ newLine=newLine+""+sarray[m];}}}shiftedLineIndexes.add(newLine);}}ls=shiftedLineIndexes;}}//Main.java importjava.util.ArrayList; publicclass Main {public static void main(String[] args) {// TODO Auto-generated method stubArrayList<String>ls=new ArrayList<String>();InputStore inputStore=new InputStore(ls);inputStore.input("input.txt");CircularShifter cs=new CircularShifter(ls);cs.shift();Alphabetizer alp=new Alphabetizer(cs.ls);alp.alpha();Output output=new Output(alp.ls);output.output("output.txt");}}KWIC 基于管道过滤器风格的JAVA 语言实现//Main类 packagekwic_pipe; importjava.io.File; importjava.util.Scanner;public class Main { public static voidmain(String[] args) { File infile = newFile("e:\\mykwic_in.txt");File outfile = new File("e:\\mykwic_out.txt");Scanner inputfile; Scanneroutputfile;try{ inputfile = newScanner(infile); outputfile =new Scanner(outfile); // 定义三个管道Pipe pipe1 = new Pipe();Pipe pipe2 = new Pipe();Pipe pipe3 = new Pipe();// 定义四种过滤器Input input = new Input(infile, pipe1); Shift shift = new Shift(pipe1, pipe2);Output output = new Output(pipe3, outfile);// 启动四种过滤器的线程input.transform()shift. transform ();output. transform ();// 直接输出结果System.out.println("----- infile -----"); String str = null; while (inputfile.hasNextLine()){ str = inputfile.nextLine();System.out.println(str);}System.out.println("input end");Thread.sleep(3000);System.out.println("----- outfile -----"); while (outputfile.hasNextLine()){ System.out.println(str);}inputfile.close();outputfile.close();} catch(Exceptione){ e.getMessage();}}}//Filter类 package kwic_pipe;import java.io.IOException;public abstract class Filter {//定义输入管道protected Pipe input; //定义输出管道 protected Pipe output;private boolean isStart = false;Filter(Pipe input, Pipeoutput){ this.input = input;this.output = output;}// 防止多次调用,调用之后线程开始执行public voidstart(){ if(!isStart){isStart = true;Thread thread = new Thread(); thread.start();}}//线程的 run 方法public voidrun(){ try{this.transform(); }catch (IOExceptione){ e.getMessage();}}//将输入数据转换为所需数据并写入输出管道//由子类实现抽象方法protected abstract void transform()throws IOException;}Pipe类package kwic_pipe;import java.io.IOException;import java.io.PipedReader;import java.io.PipedWriter;import java.io.PrintWriter;import java.util.Scanner;public class Pipe {//输入管道private Scanner pipereader;//输出管道private PrintWriter pipewriter;public Pipe(){PipedWriter pw = new PipedWriter();PipedReader pr = new PipedReader();try{pw.connect(pr);} catch (IOException e){ e.getMessage();}pipewriter = new PrintWriter(pw);pipereader = new Scanner(pr);}//读入一行数据到管道//return 读入的数据public String readerLine() throwsIOException{ return pipereader.nextLine();}//从管道输出一行数据public void writerLine(String strline) throwsIOException{ pipewriter.println(strline);}//将读管道关闭,调用该方法后,不能再从管道中读数据//如不能关闭则抛出异public void closeReader() throwsIOException{ pipereader.close();}//先刷新数据,在将写管道关闭,调用该方法后,不能向管道中写数据//如不能关闭则抛出异常public void closeWriter() throwsIOException{ pipewriter.flush(); pipewriter.close();}} Alphabetizer类package kwic_pipe;import java.io.IOException; importjava.util.ArrayList; importjava.util.Collections; public classAlphabetizer extends Filter{private ArrayList<String> al = new ArrayList<String>();Alphabetizer(Pipe input, Pipeoutput){ super(input, output);}//对读入的数据进行排序protected void transform() throws IOException {String templine = null;//读入数据while((templine = input.readerLine()) !=null){ al.add(templine);}//按字母表排序Collections.sort(al);//对排序后的数据进行输出for(int i = 0; i < al.size();i++){ output.writerLine(al.get(i));}input.closeReader();output.closeWriter();}} Shift类 packagekwic_pipe;import java.io.IOException; importjava.util.ArrayList; public classShift extends Filter{//单词的列表private ArrayList<String> wordlist = new ArrayList<String>(); //重组后的行的列表private ArrayList<String> linelist = new ArrayList<String>();Shift(Pipe input, Pipeoutput){ super(input, output);}Overrideprotected void transform() throws IOException {String templine = "";//读数据while((templine = input.readerLine()) != null){//将数据拆分为不同单词this.lineSplitWord(templine);//将单词重组为句子this.recombination();//输出重组结果for(int i = 0; i < linelist.size();i++){ output.writerLine(linelist.get(i)); }//清空wordlist、linelist和templinewordlist.clear();linelist.clear();templine = "";}input.closeReader();output.closeWriter();}//从一行中提取单词存入单词表中private void lineSplitWord(String line){String word = ""; inti = 0; while(i <line.length()){ if(line.charAt(i) != ''){ word +=line.charAt(i);}else{ wordlist.add(word);}i++;}}private void recombination(){for(int j = 0; j < wordlist.size(); j++){ String templine = ""; for (int k = wordlist.size() - 1 - j; k < wordlist.size(); k++){ templine += wordlist.get(k) + " "; } for (int m = 0; m < wordlist.size()- 1 - j; m++){ if(m != wordlist.size() - j -2){ templine += wordlist.get(m) + " ";}else{ templine +=wordlist.get(m);}}linelist.add(templine);}}}Input类 packagekwic_pipe;import java.io.File;import java.io.IOException;import java.util.Scanner;public class Input extends Filter{//输入文件的文件名private File infile;Input(File file, Pipeoutput){ super(null,output); this.infile =file;}Override //读取数据protected void transform() throws IOException {Scanner sc = new Scanner(infile); String templine = ""; while((templine =sc.nextLine()) !=null){ output.writerLine(templine);}output.closeWriter();sc.close();}}Output类 package kwic_pipe;import java.io.File; importjava.io.IOException; importjava.io.PrintWriter;public class Output extendsFilter{//输出文件的文件名private File file;Output(Pipe input, Filefile){ super(input, null);this.file = file;}//输出数据protected void transform() throws IOException {PrintWriter pw = new PrintWriter(file); String templine = "";while((templine = input.readerLine()) !=null){ pw.write(templine); pw.write("\n");}pw.flush();pw.close();input.closeReader();}}。