Java 使用模板模式设计通用流程
我有一个我为许多项目反复做的例行程序,我想推广它。我使用Java 使用模板模式设计通用流程,java,templates,design-patterns,abstract-class,Java,Templates,Design Patterns,Abstract Class,我有一个我为许多项目反复做的例行程序,我想推广它。我使用iText进行PDF操作 假设我在一个文件夹中有2000个PDF,我需要将它们压缩在一起。假设限制为每邮政编码1000 PDF。因此zip的名称将遵循以下规则:作业名称+作业顺序。例如,前1000个PDF的邮政编码名称为XNKXMN+AA,第二个邮政编码名称为XNKXMN+AB。在压缩这些PDF之前,我需要在每个PDF中添加一些文本。文本看起来类似于作业名称+作业序列+pdf序列。因此firstzip中的第一个PDF将包含以下文本XNKXM
iText
进行PDF操作
假设我在一个文件夹中有2000个PDF,我需要将它们压缩在一起。假设限制为每邮政编码1000 PDF。因此zip的名称将遵循以下规则:作业名称
+作业顺序
。例如,前1000个PDF的邮政编码名称为XNKXMN
+AA
,第二个邮政编码名称为XNKXMN
+AB
。在压缩这些PDF之前,我需要在每个PDF中添加一些文本。文本看起来类似于作业名称+作业序列
+pdf序列
。因此firstzip中的第一个PDF将包含以下文本XNKXMN
+AA
+000001
,然后是XNKXMN
+AA
+000002
。这是我的尝试
首先,我有代表我的文本的抽象类GenericText
public abstract class GenericText {
private float x;
private float y;
private float rotation;
/**
* Since the text that the user want to insert onto the Pdf might vary
* from page to page, or from logical document to logical document, we allow
* the user to write their own implementation of the text. To give the user enough
* flexibility, we give them the reference to the physical page index, the logical page index.
* @param physcialPage The actual page number that the user current looking at
* @param logicalPage A Pdf might contain multiples sub-documents, <code>logicalPage</code>
* tell the user which logical sub-document the system currently looking at
*/
public abstract String generateText(int physicalPage, int logicalPage);
GenericText(float x, float y, float rotation){
this.x = x;
...
}
}
JobGenerator.java
:我的通用API实现了我上面描述的功能
public String generatePrintJob(List<File> pdfList, String outputPath,
String printName, String seq, List<GenericText> textList, int maxSize)
for (int currentPdfDocument = 0; currentPdfDocument < pdfList.size(); currentPdfDocument++) {
File pdf = pdfList.get(currentPdfDocument);
if (currentPdfDocument % maxSize != 0) {
if(textList != null && !textList.isEmpty()){
for(GenericText gt : textList){
String text = gt.generateText(currentPdfDocument, currentPdfDocument)
//Add the text content to the PDF using PdfReader and PdfWriter
}
}
...
}else{
//Close the current output stream and zip output stream
seq = Utils.getNextSeq(seq);
jobPath = outputPath + File.separator + printName + File.separator + seq + ".zip"
//Open new zip output stream with the new <code>jobPath</code>
}
}
}
所以现在在我的主课上,我会这样做
final String printName = printNameLookup.get(baseOutputName);
String jobSeq = config.getPrintJobSeq();
final String seq = jobSeq;
GenericText keyline = new GenericText(90, 640, 0){
@Override
public String generateText(int physicalPage, int logicalPage) {
//if logicalPage = 1, Utils.right(String.valueOf(logicalPage), 6, '0') -> 000001
return printName + seq + " " + Utils.right(String.valueOf(logicalPage), 6, '0');
}
};
textList.add(keyline);
JobGenerator pjg = new JobGenerator();
pjg.generatePrintJob(...,..., printName, jobSeq, textList, 1000);
我在这个设计中遇到的问题是,即使我正确地将PDF压缩成两个zip,文本也不能正确地反映出来。打印和顺序没有相应改变,2000 PDF的打印和顺序保持为XNKXMN
+AA
,而不是前1000个PDF的打印和顺序,后1000个PDF的打印和顺序保持为XNKXMN
+AB
我的设计似乎有缺陷,请帮助
编辑:
在查看了
tototo2
code之后,我发现了我的问题。我创建了GenericText
,希望在不影响流程基本逻辑的情况下在pdf页面的任何位置添加文本。但是,根据定义,作业序列取决于逻辑,因为如果一个ZIP处理的PDF太多(>maxSize
),作业序列需要增加。我需要重新考虑这一点。当您创建一个匿名的GenerateText
时,您在重写的GenerateText
方法中使用的final seq
是真正的final,并且始终保持在创建时给定的值。您在generatePrintJob
中的else
中执行的seq
更新不起任何作用
更一般地说,您的代码看起来非常复杂,您可能应该后退一步,进行一些主要的重构
编辑:
相反,我会尝试一些不同的方法,没有模板方法模式:
int numberOfZipFiles =
(int) Math.ceil((double) pdfList.size() / maxSize);
for (int iZip = 0; iZip < numberOfZipFiles; iZip++) {
String batchSubName = generateBatchSubName(iZip); // gives AA, AB,...
for (int iFile = 0; iFile < maxSize; iFile++) {
int fileNumber = iZip * maxSize + iFile;
if (fileNumber >= pdfList.size()) // can happen for last batch
return;
String text = jobName + batchSubName + iFile;
... add "text" to pdfList.get(fileNumber)
}
}
还可以有
genericText.generateText(fileNumber)
,它本身可以分解AA000001中的文件号,但是这有点危险,因为maxSize将在两个不同的地方使用,并且可能会有类似的重复数据。当您创建匿名GenerateText
时,在重写的generateText
方法中使用的final seq
是真正的final,并且始终保持创建时给定的值。您在generatePrintJob
中的else
中执行的seq
更新不起任何作用
更一般地说,您的代码看起来非常复杂,您可能应该后退一步,进行一些主要的重构
编辑:
相反,我会尝试一些不同的方法,没有模板方法模式:
int numberOfZipFiles =
(int) Math.ceil((double) pdfList.size() / maxSize);
for (int iZip = 0; iZip < numberOfZipFiles; iZip++) {
String batchSubName = generateBatchSubName(iZip); // gives AA, AB,...
for (int iFile = 0; iFile < maxSize; iFile++) {
int fileNumber = iZip * maxSize + iFile;
if (fileNumber >= pdfList.size()) // can happen for last batch
return;
String text = jobName + batchSubName + iFile;
... add "text" to pdfList.get(fileNumber)
}
}
也可能有
genericText.generateText(fileNumber)
,它本身可以分解AA000001中的文件号,等等。但这有点危险,因为maxSize将在两个不同的地方使用,并且可能会有类似的重复数据。我有点困惑;上面的代码向列表中添加了一个GenericText
,是否还有其他内容?generatePrintJob
方法在PDF上循环,然后在该方法内部循环所有GenericText
s;即使有多个GenericText
s,如果它们都将数据打印到同一位置,似乎也会产生混乱。如果您想将单个GenericText
与单个PDF关联,为什么不这样做呢?您不需要处理文件0、1000等。它们在else
中分支,您只需要处理If
@DaveNewton中的文件:我的GenericText计划是一种灵活的向PDF添加文本的方式。如您所见,它包含(x,y)坐标以及文本的旋转。抽象方法generateText(int-physicalPage,int-logicalPage)
有助于生成序列号,就像我看第1页,那么序列号是000001
或其他格式,所以我在那里有那个抽象方法,因此,用户可以编写自己的实现,说明他们希望序列号看起来如何。我知道这个设计有缺陷。我正在努力把它弄对。@toto2:你说得对,非常感谢。我有点困惑;上面的代码向列表中添加了一个GenericText
,是否还有其他内容?generatePrintJob
方法在PDF上循环,然后在该方法内部循环所有GenericText
s;即使有多个GenericText
s,如果它们都将数据打印到同一位置,似乎也会产生混乱。如果您想将单个GenericText
与单个PDF关联,为什么不这样做呢?您不需要处理文件0、1000等。它们在else
中分支,您只需要处理If
@DaveNewton中的文件:我的GenericText计划是一种灵活的向PDF添加文本的方式。如您所见,它包含(x,y)坐标以及文本的旋转。抽象方法generateText(int physicalPage,int