1. 程式人生 > >設計模式綜合例項分析之資料庫同步系統(三)

設計模式綜合例項分析之資料庫同步系統(三)

        6. 策略模式

       由於表資料的同步方式有三種,分別是增量同步、先DeleteInsert方式、臨時表方式,因此可以定義一個同步策略介面DataSynStrategy,並提供三個具體實現類:IncSynStrategyDelAndInsSynStrategyTempTableSynStrategy。類圖如圖8所示:

8 策略模式例項類圖

在圖8中,Oracle表同步物件類OracleTableDBSynchronizer充當環境類,DataSynStrategy充當抽象策略類,其子類IncSynStrategyDelAndInsSynStrategyTempTableSynStrategy

充當具體策略類。

       在OracleTableDBSynchronizer中將DataSynStrategy作為方法synSingleTable()的區域性變數,因此OracleTableDBSynchronizerDataSynStrategy為依賴關係,如果為全域性變數,則為關聯關係。

       7. 組合模式、命令模式和職責鏈模式

在使用臨時表方式實現表同步時可以定義一系列命令物件,這些命令封裝對資料庫的操作,由於有些操作修改了資料庫結構,因此傳統的JDBC事務控制起不到作用,需要自己實現操作失敗後的回滾邏輯。此時可以使用命令模式進行設計,在設計時還可以提供巨集命令MacroCommand

,用於將一些具體執行資料庫操作的命令組合起來,形成複合命令。類圖如圖9所示(由於原始類圖比較複雜,考慮到可讀性,圖9進行了適當簡化,不過簡化了之後還是挺複雜的,微笑):

9 組合模式、命令模式和職責鏈模式例項類圖

(由於涉及到多個模式的聯用,此圖有點點複雜,偷笑

在圖9中,TempTableSynCommand充當抽象命令,MacroCommand充當巨集命令類,RenameTableCommandSynTableDataCommandRenameTableConstraintCommand充當具體命令,TempTableSynStrategy充當請求呼叫者,DataSynHelper充當請求接收者,在DataSynHelper

中定義了輔助實現臨時表方式同步的一些方法,在命令類中將呼叫這些方法。在TempTableSynCommand中聲明瞭公共的execute()方法,並提供了回滾方法undo(),其子類實現具體的執行操作與恢復操作。DataSynHelper介面聲明瞭進行資料庫操作的方法,在其子類DataSynHelperImpl中實現了這些方法。

       在TempTableSynCommand中還定義了兩個子型別的變數previousCommandnextCommnad用於儲存前一個命令和後一個命令,其中nextCommnad用於在執行完當前命令的業務邏輯後,再執行下一個命令的業務邏輯;而previousCommand用於在出現異常時,呼叫上一個命令的undo()方法實現恢復操作。此時使用了職責鏈模式,nextCommnad.execute()實現正向職責鏈,而previousCommand.undo()加上Java的異常處理機制實現反向職責鏈。

       MacroCommand是巨集命令,其程式碼片段如下所示:

public class MacroCommand extends TempTableSynCommand {
	TempTableSynCommand lastCommand = this;
	public void add(TempTableSynCommand tempTableSynCommand) {
		tempTableSynCommand.setPreviousCommand(lastCommand);
		lastCommand = tempTableSynCommand;		//建立命令鏈
	}
    protected void execute() throws Exception {
……
}
protected void undo() throws Exception {
……
}
}

在請求呼叫者類TempTableSynStrategy中通過如下程式碼片段來呼叫巨集命令物件的execute()方法:

public class TempTableSynStrategy extends DataSynStrategy {
	public String processSyn() {
		//其他程式碼省略	
		String tempTableName = generateTempTableName();
		String backupTableName =  "BAK_" + tempTableName;
		DataSynHelper dataSynHelper = new DataSynHelperImpl();
		MacroCommand marcoCommand = new MacroCommand();
		marcoCommand.add(new RenameTableConstraintCommand(dataSynHelper, tableName, destDB));
		marcoCommand.add(new SynTableDataCommand(dataSynHelper, tableName, tempTableName, srcDB, destDB));
		marcoCommand.add(new RenameTableCommand(dataSynHelper, tableName, backupTableName, destDB));
		marcoCommand.add(new RenameTableCommand(dataSynHelper, tempTableName, tableName, destDB));
		try{
			marcoCommand.execute();			
			try {
				//其他程式碼省略	
			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (Exception e){
			e.printStackTrace();
		}
//其他程式碼省略
	}
}

【本例項分析到此全部結束,希望能給各位帶來幫助,微笑!】