java - 在不修改原始源代码的情况下扩展访客模式?

标签 java design-patterns visitor-pattern extensibility

我在跨多个模块扩展访问者模式时遇到问题,您可以在评论中阅读问题的解释。

interface Example {

    interface ISource {
        Object accept(ISourceVisitor visitor);
    }

    class Module1Source1 implements ISource {
        @Override
        public Object accept(ISourceVisitor visitor) {
            return visitor.visit(this);
        }
    }

    class Module1Source2 implements ISource {
        @Override
        public Object accept(ISourceVisitor visitor) {
            return visitor.visit(this);
        }
    }

    interface ISourceVisitor {
        Object visit(Module1Source1 wheel);
        Object visit(Module1Source2 engine);
    }

    class SupportedCurrenciesVisitor implements ISourceVisitor {
        @Override
        public Object visit(Module1Source1 wheel) {
            return ImmutableList.of("USD");
        }

        @Override
        public Object visit(Module1Source2 engine) {
            return ImmutableList.of("EUR");
        }
    }

    //suppose we don't want to change the code above because it's in another library
    //I want to add one more source

    class Module2Source1 implements ISource {
        @Override
        public Object accept(ISourceVisitor visitor) {
            return null;
        }
    }

    // I cannot change ISourceVisitor, so what do I need to do?
    // one way is to create another interface

    interface IAnotherModuleSource extends ISource {
        Object accept(IThisModuleSourceVisitor visitor);
    }

    interface IThisModuleSourceVisitor extends ISourceVisitor {
        Object visit(Module2Source2 module2Source2);
    }

    class Module2Source2 implements IAnotherModuleSource {
        //it's ok
        @Override
        public Object accept(IThisModuleSourceVisitor visitor) {
            return visitor.visit(this);
        }
        //but what should we do with this:??
        @Override
        public Object accept(ISourceVisitor visitor) {
            return accept((IThisModuleSourceVisitor) visitor);
        }

        //this way if SupportedCurrenciesVisitor will be passed to the Module2Source2 we 
        //will have CCE
        //but it's ok if we pass here specific visitor for this module
    }

}

显然,如果我们将方法 getSupportedCurrency() 放在 ISource 中 不会有这样的问题,但我认为这也不是完美的方式。

问题是我们能否对 Visitor 做得更好?

或者在这种情况下您建议采取什么方法?

最佳答案

Tl;dr:您所描述的问题是尝试将模式应用于不适合的问题的结果。

“改变的原因”都分为两个基本类别:数据和功能。访问者模式以一种让您牺牲更改数据结构的能力来换取能够非常轻松地更改功能的方式,解耦了数据和功能之间的正常 OO 直接关联。添加另一个 ISourceVisitor 是微不足道的,因为这就是访问者模式旨在让您执行的操作。添加另一个 ISource 会更改您的数据结构,并迫使您更改所有功能以适应它,这明确表明您选择了错误的模式。

关于java - 在不修改原始源代码的情况下扩展访客模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26301220/

相关文章:

java - HashSet 包含重复条目

java - Spring Statemachine 状态操作与转换操作

java - 简化的访客模式

apache - Apache 负载均衡器(代理)服务器背后的真实 IP

Java编译器树api : NPE

java - 升级到 JBoss EAP 后 CXF 不工作

java.lang.Long 无法转换为 java.lang.Integer JPA GAE 和枚举

java - 适配器和访问者模式是否适合我的用例?

java - 在 JAVA 和 Spring 中设计自定义工作流程

design-patterns - 我所有的测试在 Nunit 中都被忽略