访问者模式在这里可能适用:
abstract class Document {
public abstract void accept(View view);
}
class Letter extends Document {
public void accept(View view) { view.display(this); }
}
class Email extends Document {
public void accept(View view) { view.display(this); }
}
abstract class View {
public abstract void display(Email document);
public abstract void display(Letter document);
}
访问者是较具争议的模式之一,尽管有许多变种试图克服原始模式的限制。
如果可以在 Document 中实现 accept(...) 方法,那么它将更容易实现,但该模式依赖于“this”参数的静态类型,因此我认为在 Java 中这是不可能的 - 因为“this”的静态类型取决于实现它的类,所以你必须在此情况下重复自己。
如果文档类型的数量相对较少且不太可能增长,而视图类型的数量更有可能增长,则这将起作用。否则,我会寻找一种使用第三个类来协调显示并尝试保持 View 和 Document 独立的方法。这第二种方法可能如下:
abstract class Document {}
class Letter extends Document {}
class Email extends Document {}
abstract class View {}
class LetterView extends View {}
class EmailView extends View {}
class ViewManager {
public void display(Document document) {
View view = getAssociatedView(document);
view.display();
}
protected View getAssociatedView(Document document) { ... }
}
ViewManager 的目的是将文档实例(或者如果只能打开一个给定类型的文档,则为文档类型)与视图实例(或者如果只能打开一个给定类型的视图,则为视图类型)关联起来。如果一个文档可以有多个关联的视图,则 ViewManager 的实现将如下所示:
class ViewManager {
public void display(Document document) {
List<View> views = getAssociatedViews(document);
for (View view : views) {
view.display();
}
}
protected List<View> getAssociatedViews(Document document) { ... }
}
视图-文档关联逻辑取决于您的应用程序。它可以是简单的,也可以是需要的复杂的。关联逻辑封装在ViewManager中,因此更改起来相对容易。我喜欢Drew Wills在他的答案中提到的依赖注入和配置方面的观点。
new spreadsheet().display();
,我保证人们会质疑 display 是什么样子的...他们最终会用代码测试 typeof(eachObject)。如果您更深入地解释一下 display,我会给您点赞的。 :) - JonH