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