我创建了一个面向对象的结构,其中包含 Header、Address、Subject、DetailedItem 等类。每个类都有不同类型的字段:
public class Address {
private String countryCode;
private String voivodeship;
private String county;
private String community;
// more fields, constructors, getters & setters..
}
或
public class Subject1 {
private NonPhysicalPerson nonPhysicalPerson;
private PhysicalPerson physicalPerson;
// more fields, constructors, getters & setters..
}
我有一个 PDF 表格,其中包含某项内容。约100个字段。每个字段由ID表示:
- 对于 PDF 的页眉部分:h1、h2、...、hn
- 对于 PDF 的主题 1 部分:s1、s2、...、sn
- 对于 PDF 的主题 2 部分:t1、t2、...、tn
- PDF 的详细信息部分:d1、d2、...、dn
我有一个问题。我不知道如何将这些字段映射到表单 ID。我只是想避免做类似的事情(我有特殊的类字段,其中包含每个表单字段的数据 - 我的意思是对于“h4”我必须使用 getOne()
,对于“h5”getSthDifferent()
等):
List<PDField> fields = acroForm.getFields();
for (PDField field : fields) {
String fieldName = field.getFullyQualifiedName();
// branching like that would be terrible
if (fieldName.equals("h1")) {
field.setValue(header.getFormCode());
} else if (fieldName.equals("h2")) {
field.setValue(header.getFormVariant());
} else if (fieldName.equals(...)) {
// etc...
} else if (fieldName.equals("d43")) {
field.setValue(detailedItem.getDetailsMap().getKey("d43"));
}
}
有什么方法可以优雅地做到这一点(任何设计模式或只是棘手的想法)? 我正在使用 Java、Groovy + PDFBox。
感谢您的帮助!
编辑(我的解决方案)
作为指定表单部分的面向对象表示的每个类,现在都实现 List<String> getData()
接口(interface)方法。我将类字段值添加到 List<String> data
然后在顶级类List<String> data
中添加All对于每个部分:
data.addAll(header.getData());
data.addAll(subject1.getData());
data.addAll(subject2.getData());
data.addAll(details.getData());
在我的情况下,字段的顺序始终保持不变,因此我能够仅在一个 for
中正确填写数据环形。我认为我的实现对于我的目的来说足够灵活。另外 for 循环看起来像:
for (int i = range.getStartIndex(); i < range.getEndIndex(); i++) {
fields.get(i).setValue(data.get(i));
}
哪里startIndex
和endIndex
是每个部分的界限,因此我可以选择准备填充的部分。
也许我的解决方案不是最干净的选择(+我们必须牢记性能,因此将来需要优化),但它很容易修改。我希望它能对某人有所帮助。
最佳答案
不要将 PDFField 视为愚蠢的对象/数据集合
您在 field's name
之间有直接关联和the way you set the field's value
,这可能表明您的架构存在问题。
封装 switch
的类(我们称之为类 A
)太关心你的 PDFField
对象(它询问了太多有关字段内部数据的问题并改变了它的状态)。
您对待PDFField
作为数据集合,而不是作为对象(知道如何处理其内部状态)<-- 我无法帮助您解决此问题,因为我无法查看整体代码源。
避免该切换的可能解决方案
您可以使用字典 Dictionary<String, Consumer<PDFFiled>>
和
(key, value) = ("string", (field) -> field.setValue(/*value*/))
...并且您使用 key (字段名称)询问用户,并与用户一起接受归档。 fields.forEach(field -> dict.get(filed.getName()).accept(filed)
这不是一个好的解决方案!您将避免这种切换,但代码仍然难以维护(难以扩展、难以更改等)。
其他说明
在您的情况下,您不能使用设计模式 Strategy
, Chain of responsibility
, Decorator
, Factory
因为您不能仅仅为了封装一行更改字段值的代码而创建 100 多个类。
关于java - 如何将面向对象的结构映射到表单字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47730647/