评论主题对象的面向对象设计
Object-oriented design for comment subject object
我正在尝试找出设计 class 的最佳方法,它封装了 JSON 派生的注释。每个评论都针对一个特定的主题,可以是整个文件,也可以是文件的一行。这是一个示例评论:
{
"text":"This is my favorite line!",
"path":"My file.txt",
"line":42
...
}
如果主题是整个文件,line
就是null
。
我希望 Comment
class 有一个 subject()
方法,但我不确定设计 CommentSubject
class 的最佳方法.这是我目前所拥有的:
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
在上面的示例中是相同的,所以创建新对象似乎是在浪费 space。此外,为了将 CommentSubject
对象传递给另一个 CommentSubject
构造函数,如上面的客户端代码中所示,所有主题都需要由 comment()
方法可访问的注释支持。我也不知道我怎么看 SubjectType
enum
.
我想要的是 Comment
有一个 subject()
方法并且能够区分文件和行主题。还有更好的设计吗?
如果文件注释和行注释之间的唯一区别是文件注释没有行号,您可以将 class 层次结构折叠为单个 class,并使行号可选(即 returning Integer
而不是 int
)。这将使客户端程序区分文件和行注释,因为文件注释将 return 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
的实例,该实例将收到 CommentSubject
.
的适当类型的回调
我正在尝试找出设计 class 的最佳方法,它封装了 JSON 派生的注释。每个评论都针对一个特定的主题,可以是整个文件,也可以是文件的一行。这是一个示例评论:
{
"text":"This is my favorite line!",
"path":"My file.txt",
"line":42
...
}
如果主题是整个文件,line
就是null
。
我希望 Comment
class 有一个 subject()
方法,但我不确定设计 CommentSubject
class 的最佳方法.这是我目前所拥有的:
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
在上面的示例中是相同的,所以创建新对象似乎是在浪费 space。此外,为了将 CommentSubject
对象传递给另一个 CommentSubject
构造函数,如上面的客户端代码中所示,所有主题都需要由 comment()
方法可访问的注释支持。我也不知道我怎么看 SubjectType
enum
.
我想要的是 Comment
有一个 subject()
方法并且能够区分文件和行主题。还有更好的设计吗?
如果文件注释和行注释之间的唯一区别是文件注释没有行号,您可以将 class 层次结构折叠为单个 class,并使行号可选(即 returning Integer
而不是 int
)。这将使客户端程序区分文件和行注释,因为文件注释将 return 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
的实例,该实例将收到 CommentSubject
.