免责声明:我是Java编程的新手,通常使用"极限"OOP,所以这个问题的答案可能真的很简单。
我正在Vaadin中创建一个用户界面,Vaadin是一个Web应用程序框架,为我提供了许多有用的组件。通常,我对这些组件的默认设置不是很满意。
例如,如果我希望每个TextField
组件在字段失去焦点时立即触发值更改事件。对于UploadField
, TextArea
, ComboBox
等,我想在上设置这些类的每个实例的类似设置。
目前,我的文件是这样的:
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.
}
这一点都不像一个类 !它只是静态方法的集合,这是我被告知要避免的。另外,我想把每个组件的逻辑放在一个单独的文件中。配置有时会很复杂,这样更有意义:这些都是非常小的自包含逻辑位。
以下是我考虑过的解决方案:
保持简单:我可以去掉
ConfiguredComponents
,只制作一个包含小工厂类的大包。例如,myproject.ui.components.TextFieldFactory
知道如何创建已配置的TextField
,仅此而已。优点:
- 难看的
ConfiguredComponents
类不见了
所有的逻辑都在单独的文件中。- 难看的
缺点:
- 没有单一的接口来创建我配置的组件;把它们放在一起的唯一原因是它们在同一个目录中。基本上,我必须公开很多小类,而且没有一个类或对象来管理它们。(直观地感觉这是一件非常糟糕的事情,但我不知道它是否真的是) 也没有办法覆盖或扩展静态方法,所以"伪造"UI的东西测试变得更加困难。
抽象工厂模式:我将ConfiguredComponents
变成AbstractComponentFactory
,管理许多较小的工厂。
优点:
缺点:
我需要一个
AbstractComponentFactory
的实例,每次我想在代码的任何地方为我的视图创建一个组件。这意味着要么保持一个单例对象,这有很多缺点,要么每次创建一个new AbstractComponentFactory()
。如果我想在我的小"库"中添加新组件,我必须在两到三个地方编写新代码,而不仅仅是一个。
其他一些我不知道的设计模式:我读过一些关于Builder和Facade的内容,感觉它们可能适用于这里,但是我不是很了解它们。
你将如何处理这个设计决策?
如果你的组件可以被继承,那就继续;对于要更改默认设置的每个组件,请创建一个新的派生类并在构造函数中配置settings。否则,
抽象工厂模式是一个很好的选择。我认为你对这种模式有误解。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()方法中只创建一个实例,然后尝试将该实例注入到需要创建组件的每个地方。
我能想到的一种可能的方法是将abstractfactory与服务定位器或注册表模式一起使用
因为你有无数的对象,没有复杂的实例化过程(如果有的话,求助于构建模式),你用抽象工厂创建对象,并在注册中心注册它们。无论你身在何处,都可以随时解决。
或者您可以使用简单的IOC容器,其中整个应用程序都围绕