2015-10-15 96 views
2

我有一個實現命令(使用命令模式)這兩個類,一類是創建片:重複代碼的命令類的Java

public class CommandCreateSheet implements Command { 

    private Workbook workbook; 
    private String sheetName; 

    public CommandCreateSheet(Workbook workbook, String workSheetName) { 
     this.workbook = workbook; 
     this.sheetName = workSheetName; 
    } 

    @Override 
    public void execute() { 
     this.workbook.addSheet(this.sheetName); 
    } 

    @Override 
    public void undo() { 
     this.workbook.removeSheet(this.sheetName); 
    } 
} 

,另一個是刪除:

public class CommandDeleteSheet implements Command { 

    private Workbook workbook; 
    private String sheetName; 

    public CommandDeleteSheet(Workbook workbook, String workSheetName) { 
     this.workbook = workbook; 
     this.sheetName = workSheetName; 
    } 

    @Override 
    public void execute() { 
     this.workbook.removeSheet(this.sheetName); 
    } 

    @Override 
    public void undo() { 
     this.workbook.addSheet(this.sheetName); 
    } 
} 

我怎樣才能避免這個重複的代碼?

謝謝!

+0

這段代碼對我來說很不錯。 – YoungHobbit

+1

您可以通過使用字段'workbook'和'sheetName'製作抽象超類來避免重複代碼。如果你需要大量的子類,這可能是值得的。 –

+0

對於這樣的小代碼來說,這並不值得。你仍然需要'execute'和'undo'來保持或多或少的一致性,因爲它們是特定於類的,並且你仍然需要聲明構造函數(因爲構造函數沒有被繼承),所以它贏了你沒有多少好處。 – RealSkeptic

回答

2

您可以創建一個兩個命令都可以實現的中間抽象類。

public abstract class AbstactSheetCommand implements Command 
{ 
    private Workbook workbook; 
    private String sheetName; 

    protected AbstractSheetCommand(Workbook workbook, String workSheetName) 
    { 
     this.workbook = workbook; 
     this.sheetName = workSheetName; 
    } 

    public abstract void execute(); 
    public abstract void undo(); 
} 

然後你的子類會小得多:

public class CommandCreateSheet extends AbstractSheetCommand 
{ 
    public CommandCreateSheet(Workbook workbook, String workSheetName) 
    { 
     super(workbook, workSheetName); 
    } 

    @Override 
    public void execute() { this.workbook.addSheet(this.sheetName); } 

    @Override 
    public void undo() { this.workbook.removeSheet(this.sheetName);} 
} 

public class CommandDeleteSheet extends AbstractSheetCommand 
{ 
    public CommandDeleteSheet(Workbook workbook, String workSheetName) 
    { 
     super(workbook, workSheetName); 
    } 

    @Override 
    public void execute() { this.workbook.removeSheet(this.sheetName); } 

    @Override 
    public void undo() { this.workbook.addSheet(this.sheetName); } 
} 

關於這樣做的好處是,你可以很容易地添加在相同的「類別」的新命令(這麼說)具有更多具體功能。

public class CommandRenameSheet extends AbstractSheetCommand 
{ 
    private String newWorkSheetName; 

    public CommandDeleteSheet(Workbook workbook, String oldWorkSheetName, String newWorkSheetName) 
    { 
     super(workbook, oldWorkSheetName); 
     this.newWorkSheetName = newWorkSheetName; 
    } 

    @Override 
    public void execute() 
    { this.workbook.renameSheet(this.sheetName, newWorkSheetName); } 

    @Override 
    public void undo() 
    { this.workbook.renameSheet(newWorkSheet, this.sheetName); } 
} 
+0

完美的是,我也有一個CommandSetCell類,它具有與您建議的CommandRenameSheet相同的更多屬性。 – Adrian

1

對於您這樣的短代碼,您通過嘗試消除代碼來節省很少的代碼,並且保存的代碼越多,解決方案就越複雜。

但是,這裏有一個可能的Java 8實現使用抽象類。

public abstract class SheetCommand implements Command { 

    private Runnable executeAction, undoAction; 

    public SheetCommand(Runnable executeAction, Runnable undoAction) { 
     this.executeAction = executeAction; 
     this.undoAction = undoAction; 
    } 

    @Override 
    public void execute() { 
     executeAction.run(); 
    } 

    @Override 
    public void undo() { 
     undoAction.run(); 
    } 
} 

public class CommandCreateSheet extends SheetCommand { 

    public CommandCreateSheet(Workbook workbook, String workSheetName) { 
     super(() -> workbook.addSheet(workSheetName), 
      () -> workbook.removeSheet(workSheetName)); 
    } 
} 

public class CommandDeleteSheet extends SheetCommand { 

    public CommandDeleteSheet(Workbook workbook, String workSheetName) { 
     super(() -> workbook.removeSheet(workSheetName), 
      () -> workbook.addSheet(workSheetName)); 
    } 
} 

該實現使用lambda表達式來表達您需要執行的操作。因爲lambda表達式是閉包,所以不需要明確保留實際的工作簿和表名引用 - 它們隱藏在lambda表達式中。

對於executeundo中更復雜的代碼,您可能會更好地按照原來的方式編寫這些方法,如果您嘗試使用lambda表達式,那麼最終的代碼將更復雜且難以讀取你原來有。

+0

加上一個從我。由於'SheetCommand'沒有任何抽象方法(我們知道),它可能會稍微好一些,使它非抽象並使用靜態工廠而不是子類。 –

+0

@PaulBoddington對不起發生了什麼,似乎我們並行工作。我正在考慮一個非抽象類,但是我不確定每次我們想出新命令時是否需要更改頭類(添加一個靜態方法)會更好。我想這取決於情況。 – RealSkeptic

+0

這是我的錯,發生了什麼事。我發佈了一個荒謬的答案,對同一對象持有重複引用。我同意,我們沒有足夠的信息來提供完美的解決方案。 –