Java 面向对象的评论主题对象设计
我试图找出设计类的最佳方法,该类封装JSON派生的注释。每一条评论都针对一个特定的主题,可以是一个文件整体,也可以是一行文件。下面是一个示例注释:Java 面向对象的评论主题对象设计,java,json,oop,enums,Java,Json,Oop,Enums,我试图找出设计类的最佳方法,该类封装JSON派生的注释。每一条评论都针对一个特定的主题,可以是一个文件整体,也可以是一行文件。下面是一个示例注释: { "text":"This is my favorite line!", "path":"My file.txt", "line":42 ... } 如果主题是一个整体文件,行为null 我希望Comment类具有subject()方法,但我不确定设计CommentSubject类的最佳方法。以下是我目前掌握的情况
{
"text":"This is my favorite line!",
"path":"My file.txt",
"line":42
...
}
如果主题是一个整体文件,行
为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);
...
}
...
}
doSomething(CommentSubject subject) {
Integer optLine = subject.line();
if (optLine != null) {
int line = optLine.intValue();
...
}
...
}
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;
}
}
但是,我不喜欢我当前的设计在客户端代码中需要一个新的LineSubject
对象:subject
和line
在上面的示例中是相同的,因此创建新对象似乎是浪费空间。此外,为了将一个CommentSubject
对象传递给另一个CommentSubject
构造函数,就像上面的客户机代码一样,所有主题都需要有一个可通过comment()
方法访问的注释作为支持。我也不知道我对SubjectType
enum
的看法
我想要的是
Comment
有一个subject()
方法,并且能够区分文件主题和行主题。有更好的设计吗?如果文件注释和行注释之间的唯一区别是文件注释没有行号,则可以将类层次结构折叠为单个类,并使行号可选(即返回整数而不是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) {
if (subject.type() == SubjectType.LINE) {
LineSubject line = new LineSubject(subject);
...
}
...
}
doSomething(CommentSubject subject) {
Integer optLine = subject.line();
if (optLine != null) {
int line = optLine.intValue();
...
}
...
}
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
回调您的评论处理者,如下所示:
doSomething(CommentSubject subject) {
if (subject.type() == SubjectType.LINE) {
LineSubject line = new LineSubject(subject);
...
}
...
}
doSomething(CommentSubject subject) {
Integer optLine = subject.line();
if (optLine != null) {
int line = optLine.intValue();
...
}
...
}
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
的实例,该实例将接收相应类型的CommentSubject
的回调