如何在这个生成器实现摆脱的instanceof的(How to get rid of instanc

2019-09-20 17:46发布

这个想法

我需要创建命令。 命令可以用参数进行配置。 并不是每一个命令可以收到同样的参数。 因此,一些有被忽略。

我有,我已经定义了一个构建一个抽象类的命令。 默认情况下,每一个追加参数抛出“UnsupportedOperationException异常”

public abstract class Command {

   public static abstract class CommandBuilder {

        // TODO instanceof. How to do this better?
        public CommandBuilder append(Parameter p)
            throws UnsupportedOperationException {

            if (p instanceof URLParameter)
                return append((URLParameter) p);

            if (p instanceof ActionParameter)
                return append((ActionParameter) p);

            if (p instanceof RepeatParameter)
                return append((RepeatParameter) p);

            if (p instanceof TimeOutParameter)
                return append((TimeOutParameter) p);

            return this;

        }

        public CommandBuilder append(URLParameter p)
                throws UnsupportedOperationException {

                    throw new UnsupportedOperationException(
                        "URLParameter not applicable");

        }

        public CommandBuilder append(RepeatParameter p)
            throws UnsupportedOperationException {

                throw new UnsupportedOperationException(
                    "RepeatParameter not applicable");

            }
            ...

}

如果你想有一个参数,适用于某一具体的命令,让说的FTPCommand。

你将不得不做这样的事情:

public class FTPCommand extends Command {

    public static class Builder extends CommandBuilder {

    @Override
    public CommandBuilder append(URLParameter p) {
            System.out.println("URLParemeter appended");
                return this;
            }
        }

}

因此,当提供了URLParameter它不会再抛出一个异常,而是应用它。

但是,这CommandBuilder的的客户端可能无法提供具体子类。 所以一般一个“参数”中给出。 但它需要去正确的地方(方法)

像URLParameter必须在抵达append(UrlParameter p)

我怎样才能做到这一点在干净(ER)和尼斯(R)的方式? 因为我真的不“enthousiastic”使用instanceof。

Answer 1:

这看起来像一个典型的双重分发或访客的情况。 从双派遣参考:

时调度一个函数调用,这取决于所涉及的呼叫运行时类型的两个对象的不同的具体功能的机构

ParameterCommandBuilder需要做什么彼此之间进行交互。

CommandBuilder可回拨该参数。 该Parameter对象的所有实现共同的接口和每个子类的实现将有所不同。

public CommandBuilder append(Parameter p) {
   // the append method called depends on the underlying type of 'p'
   p.append(this);
}


Answer 2:

我想补充的访问者方法的接口

interface Parameter {
    public void append(CommandBuilder builder);
}

class CommandBuilder {
    public CommandBuilder append(Parameter p) {
       p.append(this);
    }
}


文章来源: How to get rid of instanceof in this Builder implementation