如何重构内部 class MouseAdapter?
How to refactor inner class MouseAdapter?
假设我有这样一个文件:
import javax.swing.JPanel;
import java.awt.event.MouseAdapter;
public class Foo extends JPanel
{
private int m;
private int n;
private int o;
public Foo()
{
this.addMouseListener(new Bar());
}
class Bar extends MouseAdapter
{
// ...
// methods here access and modify values of the private
// instance variables.
// ...
}
}
显然我可以向 Foo
添加简单的访问器和修改器,但这很快就会变得乏味并且完全破坏了封装。我怎样才能重构这个内部 class 同时将对封装的破坏降到最低?
如果这些 class 看起来太大,那么您应该拆分它们。拆分它们的第一步是停止依赖外部 class 的私有实例变量。正如您所说,您可以添加 public getter 和 setter,但更好的做法是让 Foo 实现 Bar 的 public 接口,并让 Bar 简单地与该接口对话。并用 self 初始化每个 Bar。
public class Bar extends MouseAdapter {
public interface Caller {
void thingClicked();
...
}
}
public class Foo extends JPanel implements Bar.Caller {
...
}
所以现在在 Bar 的什么地方有类似的东西:
public void mouseUp() {
m = m + 1;
n = 0
}
您现在将拥有
public void mouseUp() {
caller.thingClicked();
}
并且,在 Foo 中:
public void thingClicked() {
m = m + 1;
n = 0
}
如果没有更多细节,很难说清楚,但基本上你的外部 class 正在响应消息,鼠标侦听器只负责传递这些消息,而不负责响应消息时发生的事情。在上面的示例中,这看起来比您已有的代码更多,但我怀疑您会发现以这种方式将其切分最终会导致更少的代码——当然还有更容易测试和重用的代码。
一种方法是将 class bar
放入一个新文件中,然后将您需要的所有内容注入到构造函数中。您需要将 int
等原始类型更改为 Integer
等对象。然后您可以创建一个 Builder class 来引导 Foo
和 Bar
的构建。为简单起见,我们假设您在所有 Foo
和 Bar
实例中需要相同的 Baz
实例:
class Builder {
// objects that both classes need are stored as member variables
// if you need multiple instances of baz you can also store a BazBuilder here
private Baz baz;
public Builder(Baz baz) {
this.baz=baz;
}
public Foo buildFoo() {
Foo foo = new Foo(baz);
return foo;
}
public Bar buildBar() {
Bar bar = new Bar(baz);
return bar;
}
}
这只是一个简单的示例,但很容易扩展。 Builder#buildFoo()
可以采用 Foo
的构造函数所需的参数,Bar
也是如此。
编辑
BazBuilder
:
的小例子
class BazBuilder {
Baz build(int value) {
return new Baz(value);
}
}
而在 Builder
中,您可以像这样使用它:
class Builder {
private BazBuilder bazBuilder;
public Build(BazBuilder bazBuilder) {
this.bazBuilder = bazBuilder;
}
public Foo buildFoo() {
Baz baz = bazBuilder.build(5);
Bar bar = new Bar(baz);
Foo foo = new Foo(baz);
foo.add(bar);
return foo;
}
}
假设我有这样一个文件:
import javax.swing.JPanel;
import java.awt.event.MouseAdapter;
public class Foo extends JPanel
{
private int m;
private int n;
private int o;
public Foo()
{
this.addMouseListener(new Bar());
}
class Bar extends MouseAdapter
{
// ...
// methods here access and modify values of the private
// instance variables.
// ...
}
}
显然我可以向 Foo
添加简单的访问器和修改器,但这很快就会变得乏味并且完全破坏了封装。我怎样才能重构这个内部 class 同时将对封装的破坏降到最低?
如果这些 class 看起来太大,那么您应该拆分它们。拆分它们的第一步是停止依赖外部 class 的私有实例变量。正如您所说,您可以添加 public getter 和 setter,但更好的做法是让 Foo 实现 Bar 的 public 接口,并让 Bar 简单地与该接口对话。并用 self 初始化每个 Bar。
public class Bar extends MouseAdapter {
public interface Caller {
void thingClicked();
...
}
}
public class Foo extends JPanel implements Bar.Caller {
...
}
所以现在在 Bar 的什么地方有类似的东西:
public void mouseUp() {
m = m + 1;
n = 0
}
您现在将拥有
public void mouseUp() {
caller.thingClicked();
}
并且,在 Foo 中:
public void thingClicked() {
m = m + 1;
n = 0
}
如果没有更多细节,很难说清楚,但基本上你的外部 class 正在响应消息,鼠标侦听器只负责传递这些消息,而不负责响应消息时发生的事情。在上面的示例中,这看起来比您已有的代码更多,但我怀疑您会发现以这种方式将其切分最终会导致更少的代码——当然还有更容易测试和重用的代码。
一种方法是将 class bar
放入一个新文件中,然后将您需要的所有内容注入到构造函数中。您需要将 int
等原始类型更改为 Integer
等对象。然后您可以创建一个 Builder class 来引导 Foo
和 Bar
的构建。为简单起见,我们假设您在所有 Foo
和 Bar
实例中需要相同的 Baz
实例:
class Builder {
// objects that both classes need are stored as member variables
// if you need multiple instances of baz you can also store a BazBuilder here
private Baz baz;
public Builder(Baz baz) {
this.baz=baz;
}
public Foo buildFoo() {
Foo foo = new Foo(baz);
return foo;
}
public Bar buildBar() {
Bar bar = new Bar(baz);
return bar;
}
}
这只是一个简单的示例,但很容易扩展。 Builder#buildFoo()
可以采用 Foo
的构造函数所需的参数,Bar
也是如此。
编辑
BazBuilder
:
class BazBuilder {
Baz build(int value) {
return new Baz(value);
}
}
而在 Builder
中,您可以像这样使用它:
class Builder {
private BazBuilder bazBuilder;
public Build(BazBuilder bazBuilder) {
this.bazBuilder = bazBuilder;
}
public Foo buildFoo() {
Baz baz = bazBuilder.build(5);
Bar bar = new Bar(baz);
Foo foo = new Foo(baz);
foo.add(bar);
return foo;
}
}