我需要super.super.method() -> 可能的设计缺陷?

  • 本文关键字:super 缺陷 method java
  • 更新时间 :
  • 英文 :


我发现自己需要在java中调用super.super.method((,这是不可能的。

我只是想知道我的设计是否有设计缺陷?

类别:

package solvers.command;
/**
 *
 * @author student
 */
public abstract class Command {
    private boolean executed;   //executed state
    /**
     * Constructs a new Command object.
     * 
     * @modifies    this.executed = false
     */
    public Command() {
        this.executed = false;
    }
    /**
     * Executes this command.
     * 
     * @modifies executed = true
     * @pre {@code !executed}
     * @throws IllegalStateException if {@code executed}
     */
    public void execute() {
        if (executed) {
            throw new IllegalStateException("solvers.command.Command.execute: already executed");
        }
        executed = true;
    }
    /**
     * Undoes this command.
     * 
     * @modifies executed = false
     * @pre {@code executed}
     * @throws IllegalStateException if {@code !executed}
     */
    public void undo() {
        if (!executed) {
            throw new IllegalStateException("solvers.command.Command.undo: not executed yet");
        }
        executed = false;
    }
    /**
     * Returns the executed state
     * 
     * @return executed state
     */
    public boolean getExecuted() {
        return executed;
    }
}
package solvers.command;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
 *
 * @author student
 */
public class CompoundCommand extends Command {
    List<Command> commands; //list of commands
    /**
     * Creates a new CompoundCommand.
     * 
     * @modifies this.commands is initialised
     */
    public CompoundCommand() {
        super();
        this.commands = new ArrayList<>();
    }
    /**
     * Adds a command to the list of commands.
     * 
     * @param command   The new command
     * @pre {@code command != null}
     * @throws IllegalArgumentException if {@code command == null}
     */
    public void add(final Command command) {
        if (command == null) {
            throw new IllegalArgumentException("solvers.command.CompoundCommand.add: "
                    + "command == null");
        }
        commands.add(command);
    }
    /**
     * Removes a command from the list of commands.
     * 
     * @param command   The command to be removed
     * @pre {@code command != null && commands.contains(command}
     * @throws IllegalArgumentException if {@code command == null || !commands.contains(command)}
     */
    public void remove(final Command command) {
        if (command == null) {
            throw new IllegalArgumentException("solvers.command.CompoundCommand.remove: "
                    + "command == null");
        }
        if (!commands.contains(command)) {
            throw new IllegalArgumentException("solvers.command.CompoundCommand.remove:"
                    + "command is not found in commands");
        }
        commands.remove(command);
    }
    /**
     * Returns if the list of commands is empty.
     * 
     * @return {@code commands.isEmpty()}
     */
    public boolean isEmpty() {
        return commands.isEmpty();
    }
    @Override
    public void execute() {
        super.execute();
        for (Command c : commands) {
            c.execute();
        }
    }
    @Override
    public void undo() {
        super.undo();
        Collections.reverse(commands);
        for (Command c : commands) {
            c.undo();
        }
        Collections.reverse(commands);
    }
}
package solvers.command;
/**
 *
 * @author student
 */
public class ExecutedCompoundCommand extends CompoundCommand {
    /**
     * Creates a new ExecutedCompoundCommand.
     */
    public ExecutedCompoundCommand() {
        super();
    }
    @Override
    public void add(final Command command) {
        if (!command.getExecuted()) {
            throw new IllegalStateException("solvers.command.ExecutedCompoundCommand.add: "
                    + "command has not been executed yet.");
        }
        super.add(command);
    }
    @Override
    public void execute() {
        super.super.execute(); /* Does not work obviously */
        for (Command c : commands) {
            if (!c.getExecuted()) {
                c.execute();
            }
        }
    }
}

基本上,我确实希望命令的execute()的安全性,而我不希望ExecutedCompoundCommand实现CompoundCommand的execute((,但我确实希望只依赖于CompoundCommand的add((、remove((和undo((操作。

作为一名学生,在一个需要javadoc和单元测试的项目中,确实需要尽可能少的代码重复,因为这只会带来更多的工作。

我认为这是一个设计缺陷。您可以应用模板方法模式〔GOF 325〕

意图:在操作中定义算法的骨架,定义子类的一些步骤。Template方法允许子类重新定义在不改变算法的情况下执行算法的某些步骤结构

从"四人帮"设计模式

您需要确保执行了某些步骤。因此,您将制作一个最终的模板方法execute((并委托给doExecute((方法,该方法可以添加额外的逻辑,并且需要由子类实现。

public final void execute() {
  importantOperation();
  runsAlways();
  doExecute();
}
public abstract void doExecute(); // Override in subclasses

有几种方法可以解决这个问题,最好的方法取决于您的意图。这里有几个建议:

创建一个新的类CommandList,它支持add((、remove((和undo((操作。

CompoundCommand扩展了Command并具有CommandList。

ExecutedCompoundCommand扩展了Command并具有CommandList。

另一种选择是创建一个新的Command子类,该子类支持常见操作并继承Command的execute((方法。

CompoundCommand将对其进行扩展并覆盖执行。

ExecutedCompoundCommand也会扩展它,因此它的super.execute((将是Command execute((。

将委托模式用于通用功能,而不是继承。或者模板模式(如果要使用继承(。

看看这里。基本上,它解释了为什么你永远不应该做你想做的事情

引用自链接:

你不应该绕过父类的行为。有时可以绕过自己类的行为(特别是在同一方法中(,但不能绕过父母的行为,这是有道理的。

在链接中显示的示例中,所提出的论点是,可以说,"中间"类正在实现一些功能或有效性检查,而通过"跳过"层次结构中的一个类可以绕过这些功能或检查。

阅读本文了解封装的好处。

最新更新