我试图找出设计类的最佳方法,它封装了JSON派生的注释。每个评论都针对特定主题,可以是整个文件,也可以是文件的一行。这是一个示例评论:
{
"text":"This is my favorite line!",
"path":"My file.txt",
"line":42
...
}
如果主题是整体文件,则line
为null
。
我希望Comment
类有subject()
方法,但我不确定设计CommentSubject
类的最佳方法。这就是我到目前为止所拥有的:
import javax.json.JsonObject;
class Comment {
private final JsonObject json;
private final CommentSubject subject;
public JsonObject json() { return json; }
public CommentSubject subject() { return subject; }
public Comment(JsonObject json) {
...
this.json = json;
subject = json.isNull("line") ? new FileSubject(this) :
new LineSubject(this);
...
}
...
}
abstract class CommentSubject {
enum SubjectType {
FILE, LINE
}
public abstract SubjectType type();
public abstract String path();
protected abstract Comment comment();
}
class FileSubject extends CommentSubject {
private final Comment comment;
private final String path;
public FileSubject(Comment comment) {
this.comment = comment;
path = comment.json().getString("path");
}
public FileSubject(CommentSubject subject) {
this(subject.comment());
}
@Override public SubjectType type() { return SubjectType.FILE; }
@Override public String path() { return path; }
@Override protected Comment comment() { return comment; }
...
}
class LineSubject extends CommentSubject {
private final Comment comment;
private final String path;
private final int line;
public LineSubject(Comment comment) {
this.comment = comment;
path = comment.json().getString("path");
line = comment.json().getInt("line");
}
public LineSubject(CommentSubject subject) {
this(subject.comment());
}
@Override public SubjectType type() { return SubjectType.LINE; }
@Override public String path() { return path; }
@Override protected Comment comment() { return comment; }
public int line() { return line; }
...
}
客户端代码可能如下所示:
doSomething(CommentSubject subject) {
if (subject.type() == SubjectType.LINE) {
LineSubject line = new LineSubject(subject);
...
}
...
}
但是,我不喜欢我的当前设计需要客户端代码中的新LineSubject
对象这一事实:subject
和line
在上面的示例中是相同的,所以新的对象创建似乎浪费了空间。此外,为了将CommentSubject
对象传递给另一个CommentSubject
构造函数,如上面的客户端代码所示,所有主题都需要由comment()
方法可访问的注释支持。我也不知道我对SubjectType
enum
的看法。
我想要的是Comment
使用subject()
方法并能够区分文件和线条主题。那里有更好的设计吗?
答案 0 :(得分:1)
如果文件注释和行注释之间的唯一区别是文件注释没有行号,则可以将类层次结构折叠为单个类,并使行号可选(即返回{{ 1}}而不是Integer
)。这将允许客户端程序区分文件和行注释,因为文件注释将返回行号的int
:
null
客户端可以编写如下内容:
public class CommentSubject {
private final Integer line;
private final String path;
private final String comment;
public String path() { return path; }
public Integer line() { return line; }
public Comment comment() { return comment; }
public static CommentSubject forFile(String p, String c) {
return new CommentSubject(p, null, c);
}
public static CommentSubject forLine(String p, int i, String c) {
return new CommentSubject(p, i, c);
}
private CommentSubject(String p, Integer i, String c) {
path = p;
line = i;
comment = c;
}
}
如果您希望避免在客户端中进行有条件调度,您可以采用类似访问者的方式,并让doSomething(CommentSubject subject) {
Integer optLine = subject.line();
if (optLine != null) {
int line = optLine.intValue();
...
}
...
}
回复您评论的处理者,如下所示:
CommentSubject
请注意评论,路径和行如何隐藏在interface CommentProcessor {
void onFileComment(String path, String comment);
void onLineComment(String path, int line, String comment);
}
public class CommentSubject {
private final Integer line;
private final String path;
private final String comment;
public void process(CommentProcessor p) {
if (line != null) {
p.onLineComment(path, line.intValue(), comment);
} else {
p.onFileComment(path, comment);
}
}
public static CommentSubject forFile(String p, String c) {
return new CommentSubject(p, null, c);
}
public static CommentSubject forLine(String p, int i, String c) {
return new CommentSubject(p, i, c);
}
private CommentSubject(String p, Integer i, String c) {
path = p;
line = i;
comment = c;
}
}
中。现在访问它们的唯一方法是传递CommentSubject
的实例,该实例将收到适当类型的CommentProcessor
的回调。