【问题标题】:Patterns for making two packages as loosely coupled as possible使两个包尽可能松耦合的模式
【发布时间】:2021-10-24 11:29:24
【问题描述】:

所以我正在学习为软件设计入门课程构建解析器。

我已经构建了一个标记器包,它将我的输入字符串拆分为具有值和类型的 getter 的 Token 对象。我还可以为当前令牌的值和类型返回一个原始字符串。

我的 Tokenizer 面向公众的界面目前看起来像这样。

public Tokenizer(Grammar rules, String input)
public Token getCurrentToken() {...} // Token has public getters similar to the two methods below
public String getCurrentValue() {...}
public String getCurrentType() {...}
public void nextToken() throws InvalidTokenException {...}
public void previousToken() {...}

在我的 Parser 类中,我还有一个 TokenReceiver(接口)和一个 TokenizerAdapter 类(实现 Receiver 和我的特定标记器)

  public void next();
  public Token getToken();
  public String getType();
  public String getValue();
  public Token getToken();
}

规则是解析中的每个不同步骤都必须使用与其他包的任何实现细节尽可能松散耦合的不同包完成,即解析器理论上应该与 any 一起工作 我找到的分词器(例如在 Github 上),而不仅仅是我自己的分词器实现,只要我为它制作了一个适配器。

如果我从 Tokenizer 发回 Token 对象,那么我的解析器将必须知道 Token 对象(特别是 getter 方法),这增加了我的 Tokenizer 实现的耦合。

直接返回值和类型的字符串,然后在 Parser 包中创建另一个 Token 类并重新创建 Tokens 对象对我来说直觉上是错误的。适配器类中 Token 的匿名内部类能否成为一个好的解决方案?

我正在寻找什么样的模式或概念可以帮助我从 Tokenizer 引用我的 Token,同时保持与我的特定 tokenizer 实现的松散耦合。

很抱歉,如果问题真的很愚蠢而答案真的很明显,设计模式对我来说仍然非常抽象,我们正在学习其中的很多,我很难知道在不同的情况下使用哪一种。

【问题讨论】:

    标签: java design-patterns lexical-analysis


    【解决方案1】:

    您考虑过以下几点

    public interface Token {
       String getType();
       String getValue();
    }
    
    public interface Tokenizer {
       // either 
       Iterable<Token> parse(String input);
    
       // or
       Stream<Token> parse(String input);
    }
    
    public class GrammarTokenizer implements Tokenizer {
       private final Grammar grammar;
    
       // constructor 
    
       // method implementations 
    } 
    

    【讨论】:

    • 否,将其添加到 Tokenizer 或 Parser 包中?
    • 不管它们在哪个包中。使用这种方法,您可以从自定义类中删除所有 nextToken() currentValue() 方法,因为 Iterable 和/或 Stream提供这个
    • 谢谢。真正有用的答案:)
    • 注意:使用我的方法,您的 Tokenizer 可以是不可变的/线程安全的,并且可重复用于多个输入
    【解决方案2】:

    当您想在类之间传递一些对象同时试图避免类之间的紧密耦合时,实现接口可能会有所帮助。在您的情况下,也许创建一个令牌接口并从您的令牌生成器和解析器中引用该接口,而不是直接引用具体的令牌类(令牌类应该实现令牌接口)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      • 2017-05-09
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多