三種典型的數據流風格
§ Batch Sequential (批處理)
§ Pipe-and-Filter (管道-過濾器)
§ Process Control(過程控制,3.7)
批處理風格:
直觀結構
批處理風格-基本定義
§每個處理步驟是一個獨立的程序
§每一步必須在前一步結束後才能開始
§數據必須是完整的,以整體的方式傳遞
§典型應用:
–傳統的數據處理
–程序編譯/CASE(computer aided software engineering)工具
批處理風格-基本構成
§基本組件:獨立的應用程序
§連接件:某種類型的媒質(magnetic tape)
§表達拓撲結構:連接件定義了相應的數據流圖
§每一步驟必須在前一步驟完全結束之後方能開始
程序:#include <iostream>
#include<fstream>
using namespace std;
bool writeFile(constchar* strPath,char strConcern[],int length)
{
ofstream outfile;
outfile.open(strPath,ios::app);
if(!outfile)
{
cerr<<"openerror!"<<endl;
return false;
}
outfile.write(strConcern,length);
outfile.close();
return true;
}
bool ReadFile(constchar * strPath,char strConcern[],int length)
{
ifstream infile;
infile.open(strPath,ios::binary);
if(!infile)
{
cerr<<"openerror"<<endl;
return false;
}
while(!infile.eof())
{
infile.read(strConcern,length);
}
return true;
}
bool factory1()
{
char str[20]="helloworld";
charstrpath[20]="E:\\text1.txt";
bool b=writeFile(strpath,str,sizeof(str));
if(!b)
{
return false;
}
return true;
}
bool factory2()
{
char str[20];
char strpath[20]="E:\\text1.txt";
bool b=ReadFile(strpath,str,sizeof(str));
cout<<str<<endl;
cout<<str<<endl;
charstrpath1[20]="E:\\text2.txt";
boolbw=writeFile(strpath1,str,sizeof(str));
bw=writeFile(strpath1,"第二道工序",sizeof(str));
if(!b||!bw)
{
return false;
}
return true;
}
int main()
{
char strpath[40]="E:\\text2.txt";
char str[20];
bool b1=factory1();
bool b2=factory2();
bool b=ReadFile(strpath,str,sizeof(str));
if(b&&b1&&b2)
{
cout<<str<<endl;
}
//cout << "Hello world!"<< endl;
return 0;
管道過濾器風格:
組件:過濾器,處理數據流
–一個過濾器封裝了一個處理步驟
–數據源點和數據終止點可以看作是特殊的過濾器過濾器對輸入流進行處理、轉換,處理後的結果在輸出端流出。§每個組件都有輸入/輸出集合,組件在輸入處讀取數
據流,經過內部處理,在輸出處生成數據流。
連接件:管道,連接一個源和一個目的過濾器
–轉發數據流
–數據可能是ASCII字符形成的流連接件位於過濾器之間,起到信息流的導管的作
用,被稱爲管道。接件就象是數據流傳輸的管道,將一個過濾器的輸出傳到另一過濾器的輸入。
管道過濾器優點:由於每個組件的行爲不受其他組件的影響,整個系統的行爲易於理解
§系統中的組件具有良好的隱蔽性和高內聚、低耦合的特點;
–支持軟件複用:
•允許設計者將整個系統的輸入/輸出行爲看成是
多個過濾器的行爲的簡單合成;
•只要提供適合在兩個過濾器之間傳送的數據,任何兩個過濾器都可被連
接起來;
–系統維護和增強系統性能簡單:
•新的過濾器可以添加到現有系統中來,
舊的可以被改進的過濾器替換掉;
允許對一些如吞吐量、死鎖等屬性的分析;
§支持並行執行:
–每個過濾器是作爲一個單獨的任務完成,因此可與
其它任務並行執行。
管道-過濾器風格的缺點:
§通常導致進程成爲批處理的結構
–這是因爲雖然過濾器可增量式地處理數據,但它們
是獨立的,所以設計者必須將每個過濾器看成一個
完整的從輸入到輸出的轉換;
§不適合處理交互的應用
–當需要增量地顯示改變時,這個問題尤爲嚴重;
處理兩個獨立但又相關的數據流是可能會遇到困難
§在數據傳輸上沒有通用的標準,每個過濾器都增加
瞭解析和合成數據的工作,這樣就導致了系統性能
下降,並增加了編寫過濾器的複雜性。
–絕大部分處理時間消耗在格式轉換上(需要對數據傳
輸進行特定的處理時,會導致對於每個過濾器的解析
輸入和格式化輸出要做更多的工作,帶來系統複雜性
的上升)
過濾器與批處理比較:
程序:管道-過濾器軟件體系結構
(1)在dos提示符下輸入下面的命令:
dir | more
使得當前目錄列表在屏幕上逐屏顯示。
dir的輸出的是整個目錄列表,它不出現在屏幕上而是由於符號“|”的規定,成爲下一個命令more的輸入,more命令則將其輸入一屏一屏地顯示,成爲命令行的輸出。
(2)Java I/O流中的管道流類PipedInputStream和PipedOutputStream可以方便地實現管道-過濾器體系結構,這兩個類的實例對象要通過connect方法連接。
下面程序的功能是sender發送“Hello,receiver! I`m sender”給receiver,然後receiver接受後顯示出來並且在前面加上“the following is from sender”的信息。管道流內部在實現時還有大量的對同步數據的處理,管道輸出流和管道輸入流執行時不能互相阻塞,所以一般要開啓獨立線程分別執行,順便複習了多線程操作。
import java.io.*;
import java.util.*;
public class TestPiped{
public static void main(String [] args){
sender s = new sender();
receiver r = new receiver();
PipedOutputStream out = s.getOut();
PipedInputStream in = r.getIn();
try{
in.connect(out);
s.start();
r.start();
}catch(Exception e){
e.printStackTrace();
}
}
}
class sender extends Thread {
PipedOutputStream out = new PipedOutputStream();
publicPipedOutputStream getOut(){
return out;
}
public void run() {
String str = "Hello,receiver ! I`msender\n";
try {
out.write(str.getBytes());
out.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
class receiver extends Thread {
PipedInputStream in = new PipedInputStream();
public PipedInputStream getIn() {
return in;
}
public void run(){
byte [] buf = new byte[1024];
try {
int len = in.read(buf);
System.out.println("the following is from sender:\n"+newString(buf,0,len));
in.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
程序的執行結果:
thefollowing is from sender:
Hello,receiver ! I`m sender