开发者

What is the correct OO design for maximum re-use and efficiency?

Assume I have a Java package (both .jar and source codes). Here are definitions of what some of the classes I would like to re-use.

abstract class Tree {
  public abstract Tree[] children();
  public void print();
}

class LabeledTree extends Tree implements Label {
  Label label;
  Tree[] daughterChildren;
  public Tree[] children();
}

class Demo {
  public static void main(String[] args) {
    Parser p = new Parser();
    String[] sent = { "This", "is", "an", "easy", "sentence", "." };
    Tree parse = p.apply(sent);
    parse.p开发者_运维百科rint();
  }
}

The apply method above returns a LabeledTree. Now, I would like to create my own type of tree, say MyTree, which has the following structure.

class MyTree {
  int value;
  Label label;
  public void myPrint();
}

Where do you suggest I should put this class in the inheritance tree so that I can directly instantiate objects of this class from the apply method? How do you think I should be going to design my system to maximize software re-use and not have to parse every tree to build objects of MyTree?


Several comments:

First of all, your tree definition exposes an important detail - each tree object is a node. This creates a whole bunch of conceptual units. In a real API, you would have a Tree interface, and an implementation that uses Nodes. All the data members would be in the node, except for the root node, which would be in your TreeImpl.

Second, I'm a big believer in naming being a critical first step for good and readable code, and that it often has an impact on the quality of your OO design. A tree should not simply implement label. Can you say: "A tree is a label"? On the other hand, if you had something like: "TreeNode implements HasLabel", it would be clearer - "your tree node has a label".

Third, you are encountering the well known OOP problems of conformance and variance. With your current design, your root of the labeled tree has a label, but the lower nodes (which are simply Trees) do not have to be a labeled tree. This would be fun to debug. Generics can help you address this, but make sure to read Effective Java to understand how constraining generic types work.


I agree with @Uri that making Tree an Interface instead of an Abstract class would be an improvement.

If your parser doesn't know about subclasses of Tree, then one way is a reflection based scheme using Class.forName. Another way to deal with it would be to use a system where extension register when they are installed(A example here is the Eclipse plugin registry, although its a very complicated example of this pattern).

Your larger question is really about how to best organize parsers written in an OO language. There are many, many books on this subject. One that you might try looking at is this book:

Programming Language Processors in Java: Compilers and Interpreters David Watt (Author), Deryck Brown (Author)

It's available on Amazon and is helpful is starting to understand how to design language parsers. The examples are all in Java.

Also, if you have a grammar, you could try running it through Antlr and looking at the output for good examples of how to organize a parser.

http://www.antlr.org/


There are pieces missing from your puzzle making a complete answer impossible from me, but as a first guess, I'd suggest genericizing your code as a first step towards generalizing it and allowing for easier extension.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜