2015-10-15 72 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

这是我的错,发生了什么事。我发布了一个荒谬的答案,对同一对象持有重复引用。我同意,我们没有足够的信息来提供完美的解决方案。 –