Java替代开启对象类型

时间:2017-03-08 14:06:15

标签: java

我想在Java 8中使用命令模式将各种命令传递给各种类的对象。问题在于,对象具有我不想暴露公共制定者的成员;我希望通过命令操纵这些成员。我的问题是如何将这些成员(或更好的,包私有的setter)暴露给命令。如果我将它们作为界面的一部分,那么我将它们公之于众。继承它们不是一种选择,因为我需要多重继承。那么如果命令既不是作为类的一部分暴露,也不是作为接口的一部分,那么命令如何知道setter是否可用?

我想到的最好的解决方案是让相关的类切换命令类型并在类中实现命令完全的执行(因此成员可以是私有的 - 甚至更好),只需从命令类中提取必要的信息。但是,用OO语言切换对象类型的想法让我觉得有些污点。还有更好的方法吗?

3 个答案:

答案 0 :(得分:2)

使用Visitor Pattern

  • 您的可配置类是Visitor
  • 您的命令类是Element
  • 将可配置类传递给命令的accept方法,该命令调用与命令类型对应的方法。

以下是一个例子:

interface CommandVisitor {
    void visit(SetCommand1 cmd);
    void visit(SetCommand2 cmd);
}
interface Command {
    void accept(CommandVisitor v);
}
class SetCommand1 : Command {
    public void accept(CommandVisitor v) {v.visit(this);}
}
class SetCommand2 : Command {
    public void accept(CommandVisitor v) {v.visit(this);}
}

现在,您的可配置类可以为visitSetCommand1实施SetCommand2次重载,这将会接收"回调"根据传递给你的命令类型。

答案 1 :(得分:1)

嵌套类可以访问其封闭类的私有成员,因此您可以将命令设置为嵌套类:

cel

然后:

interface Command {
    void execute();
}

class Model {
    private int fieldA;
    private String fieldB;

    ...

    public Command getCommand() {
        return new MyCommand();
    }

    ...

    private class MyCommand implements Command {
        @Override
        public void execute() {
            fieldA = 10;
            fieldB = "Foo";
            //Or use setter...
        }
    }
}

这种方式Model model = ...; Command command = model.getCommand(); //usage... 可以访问MyCommand个字段,但其他任何内容都无法访问。

答案 2 :(得分:0)

在此解决方案中,您强制对象自己提供命令。这允许隐藏对象的内部。这些命令都来自Command

@FunctionalInterface
public interface Command { public void execute(); }

例如CommandA

public interface CommandA extends Command { }

应该使用此框架的对象应该实现Commandable。此接口为每个受支持的命令都有一个方法,并允许对象返回给定命令的特定实现。

public interface Commandable { public CommandA getCommandA(); }

以下列方式使用它。

public class Type implements Commandable {

    private boolean isRunning = false;

    public CommandA getCommandA() {
        return () -> {isRunning = true;};
    }

    public boolean isRunning() {
        return isRunning;
    }

    public static void main(String[] args) {
        Type type = new Type();
        System.out.println(type.isRunning());

        Commandable object = type;
        CommandA command = object.getCommandA();
        command.execute();

        System.out.println(type.isRunning());
    }

}

输出

false
true

或者,如果您不希望对象实现Commandable,您可以创建某种命令注册表并强制每个对象在那里注册命令(它支持)的实现。