設計模式綜合例項分析之資料庫同步系統(三)
6. 策略模式
由於表資料的同步方式有三種,分別是增量同步、先Delete後Insert方式、臨時表方式,因此可以定義一個同步策略介面DataSynStrategy,並提供三個具體實現類:IncSynStrategy、DelAndInsSynStrategy和TempTableSynStrategy。類圖如圖8所示:
圖8 策略模式例項類圖
在圖8中,Oracle表同步物件類OracleTableDBSynchronizer充當環境類,DataSynStrategy充當抽象策略類,其子類IncSynStrategy、DelAndInsSynStrategy和TempTableSynStrategy
在OracleTableDBSynchronizer中將DataSynStrategy作為方法synSingleTable()的區域性變數,因此OracleTableDBSynchronizer與DataSynStrategy為依賴關係,如果為全域性變數,則為關聯關係。
7. 組合模式、命令模式和職責鏈模式
在使用臨時表方式實現表同步時可以定義一系列命令物件,這些命令封裝對資料庫的操作,由於有些操作修改了資料庫結構,因此傳統的JDBC事務控制起不到作用,需要自己實現操作失敗後的回滾邏輯。此時可以使用命令模式進行設計,在設計時還可以提供巨集命令MacroCommand
圖9 組合模式、命令模式和職責鏈模式例項類圖
(由於涉及到多個模式的聯用,此圖有點點複雜,)
在圖9中,TempTableSynCommand充當抽象命令,MacroCommand充當巨集命令類,RenameTableCommand、SynTableDataCommand和RenameTableConstraintCommand充當具體命令,TempTableSynStrategy充當請求呼叫者,DataSynHelper充當請求接收者,在DataSynHelper
在TempTableSynCommand中還定義了兩個子型別的變數previousCommand、nextCommnad用於儲存前一個命令和後一個命令,其中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();
}
//其他程式碼省略
}
}
【本例項分析到此全部結束,希望能給各位帶來幫助,!】