我可以使用哪种设计模式来提供创建 "pre-configured" UI 组件的几种方法
Which design pattern can I use to supply several methods that create "pre-configured" UI components
免责声明:我是 Java 编程的新手,并且通常使用“极端”OOP,所以这个问题的答案可能非常简单。
我正在 Vaadin 中创建一个用户界面,这是一个为我提供许多有用组件的 Web 应用程序框架。通常,我对这些组件的默认设置并不完全满意。
例如,如果我希望每个 TextField
组件在字段失去焦点时立即触发值更改事件。 UploadField
、TextArea
、ComboBox
等有类似的设置,我想在 每个 实例上设置 classes .
目前,我拥有的是这样的:
public class ConfiguredComponents {
public static TextField createConfiguredTextField(String caption) {
TextField field = new TextField(caption);
field.setImmediate(true);
field.setSomeOtherOptions();
...
return field;
}
public static UploadField createConfiguredUploadField(...) {
...
}
// etc.
}
这完全不像 class!它只是静态方法的集合,我被告知要避免。另外,我想将每个组件的逻辑放在一个单独的文件中。配置有时会非常复杂,这样更有意义:这些都是非常小的独立逻辑位。
以下是我考虑过的解决方案:
保持简单:我可以去掉ConfiguredComponents
,做一个大的包 包含小工厂 classes。例如,myproject.ui.components.TextFieldFactory
知道如何创建已配置的 TextField
,仅此而已。
优点:
- 丑
ConfiguredComponents
class不见了
- 所有逻辑都在单独的文件中。
缺点:
- 没有用于创建已配置组件的单一界面;唯一让它们在一起的是它们在同一个目录中。基本上,我必须公开很多微小的 classes,并且没有单个 class 或对象管理它们。 (直觉上感觉这是一件很糟糕的事情,但我不知道它是否真的是。)
- 也没有办法覆盖或扩展静态方法,因此“伪造”UI 用于测试的东西变得更加困难。
抽象工厂模式:我把ConfiguredComponents
变成了一个AbstractComponentFactory
管理着很多小工厂。
优点:
- 所有逻辑都在单独的文件中。
- 实际配置我的组件的逻辑完全在幕后。
缺点:
每次我想在代码中的任何位置为我的视图创建一个组件时,我都需要一个 AbstractComponentFactory
的实例。这意味着要么保留一个单例对象,has a lot of downsides,要么每次都创建一个 new AbstractComponentFactory()
。
如果我想向我的小“库”中添加新组件,我必须在两三个地方而不是一个地方编写新代码。
一些我不知道的其他设计模式: 我读过一些关于 Builder,和Facade,感觉可能适用于这里,但我不是很了解。
您将如何处理这个设计决策?
我认为一种可能的方法是将 AbrstractFactory 与 Service Locator or Registry patterns
一起使用
因为你有无数的对象没有复杂的实例化过程(如果是的话求助于构建模式),你用抽象工厂创建对象并将它们注册到注册表中。随时随地根据需要解决它们。
或者您可以求助于简单的 IOC 容器,您的整个应用程序都围绕着
如果你的组件可以被继承,那就继续吧;对于要更改默认设置的每个组件,在构造函数中创建一个新的派生 class 和配置设置。否则,
抽象工厂模式是个不错的选择。我认为您对这种模式有误解。 AbstractComponentFactory
只是一个接口,它不管理任何东西。该界面如下所示:
interface AbstractComponentFactory {
public TextField createTextFiled(...);
public UploadField createUploadFiled(...);
...
}
在你的情况下,我认为你只需要一个工厂实现:
class MaurisComponentFactory implements AbstractComponentFactory {
public TextField createTextFiled(...) {
new ... config ... return;
}
public UploadField createUploadFiled(...) {
new ... config ... return;
}
...
}
正如您所说,我们既不应该使用 Singleton,也不应该每次都创建新的 MaurisComponentFactory
。相反,我们应该在 main() 方法中只创建一个实例,然后尝试将这个实例注入到每个需要创建组件的地方。
免责声明:我是 Java 编程的新手,并且通常使用“极端”OOP,所以这个问题的答案可能非常简单。
我正在 Vaadin 中创建一个用户界面,这是一个为我提供许多有用组件的 Web 应用程序框架。通常,我对这些组件的默认设置并不完全满意。
例如,如果我希望每个 TextField
组件在字段失去焦点时立即触发值更改事件。 UploadField
、TextArea
、ComboBox
等有类似的设置,我想在 每个 实例上设置 classes .
目前,我拥有的是这样的:
public class ConfiguredComponents {
public static TextField createConfiguredTextField(String caption) {
TextField field = new TextField(caption);
field.setImmediate(true);
field.setSomeOtherOptions();
...
return field;
}
public static UploadField createConfiguredUploadField(...) {
...
}
// etc.
}
这完全不像 class!它只是静态方法的集合,我被告知要避免。另外,我想将每个组件的逻辑放在一个单独的文件中。配置有时会非常复杂,这样更有意义:这些都是非常小的独立逻辑位。
以下是我考虑过的解决方案:
保持简单:我可以去掉
ConfiguredComponents
,做一个大的包 包含小工厂 classes。例如,myproject.ui.components.TextFieldFactory
知道如何创建已配置的TextField
,仅此而已。优点:
- 丑
ConfiguredComponents
class不见了 - 所有逻辑都在单独的文件中。
缺点:
- 没有用于创建已配置组件的单一界面;唯一让它们在一起的是它们在同一个目录中。基本上,我必须公开很多微小的 classes,并且没有单个 class 或对象管理它们。 (直觉上感觉这是一件很糟糕的事情,但我不知道它是否真的是。)
- 也没有办法覆盖或扩展静态方法,因此“伪造”UI 用于测试的东西变得更加困难。
- 丑
抽象工厂模式:我把
ConfiguredComponents
变成了一个AbstractComponentFactory
管理着很多小工厂。优点:
- 所有逻辑都在单独的文件中。
- 实际配置我的组件的逻辑完全在幕后。
缺点:
每次我想在代码中的任何位置为我的视图创建一个组件时,我都需要一个
AbstractComponentFactory
的实例。这意味着要么保留一个单例对象,has a lot of downsides,要么每次都创建一个new AbstractComponentFactory()
。如果我想向我的小“库”中添加新组件,我必须在两三个地方而不是一个地方编写新代码。
一些我不知道的其他设计模式: 我读过一些关于 Builder,和Facade,感觉可能适用于这里,但我不是很了解。
您将如何处理这个设计决策?
我认为一种可能的方法是将 AbrstractFactory 与 Service Locator or Registry patterns
一起使用因为你有无数的对象没有复杂的实例化过程(如果是的话求助于构建模式),你用抽象工厂创建对象并将它们注册到注册表中。随时随地根据需要解决它们。
或者您可以求助于简单的 IOC 容器,您的整个应用程序都围绕着
如果你的组件可以被继承,那就继续吧;对于要更改默认设置的每个组件,在构造函数中创建一个新的派生 class 和配置设置。否则,
抽象工厂模式是个不错的选择。我认为您对这种模式有误解。 AbstractComponentFactory
只是一个接口,它不管理任何东西。该界面如下所示:
interface AbstractComponentFactory {
public TextField createTextFiled(...);
public UploadField createUploadFiled(...);
...
}
在你的情况下,我认为你只需要一个工厂实现:
class MaurisComponentFactory implements AbstractComponentFactory {
public TextField createTextFiled(...) {
new ... config ... return;
}
public UploadField createUploadFiled(...) {
new ... config ... return;
}
...
}
正如您所说,我们既不应该使用 Singleton,也不应该每次都创建新的 MaurisComponentFactory
。相反,我们应该在 main() 方法中只创建一个实例,然后尝试将这个实例注入到每个需要创建组件的地方。