使用抽象方法设计通用API,但在传递给匿名类时必须使用final 变量。有更好的方法来实现这一点吗?
我正在尝试创建一个在 iText 之上运行的通用 API。该API的功能之一是允许用户将PDF分割为单独的页面,并允许用户在分割后将文本列表添加到每个pdf页面上。例如,一个20页的pdf,运行此过程后,我将有20个1页pdf,第一个pdf上将有一个文本000001,最后一个pdf上将有000020 pdf。因此,为了实现这一目标,我使用抽象方法,允许开发人员根据给定当前页码的文本格式编写代码。
public abstract class GenericText {
/**
* The X position of the text. (0, 0) is at the bottom left
*/
private float x;
/**
* The Y position of the text. (0, 0) is at the bottom left
*/
private float y;
/**
* The rotation of the text. Rotation 0, 90, 180, 270
*/
private float rotation;
/**
* <code>com.itextpdf.text.pdf.BaseFont</code>. Determine the font for the text
*/
private BaseFont font;
/**
* Determine the font size of the text
*/
private float fontSize;
/**
* This tells whether text can only be placed first page or on every page
*/
private ComponentPlacement placement;
/**
* 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);
...
}
PdfPrcessor.java:这是分割发生的地方
/**
* This is the main process that will split the pdf into individual page, and text to each page
*/
public void splitPdf(String inputPdf, boolean isSplit, List<GenericText> textList,
String outputDir, String baseOutputName, String outputPdfName) throws IOException, DocumentException{
...
PdfReader reader = new PdfReader(inputPdf)
PdfContentByte cb = ... ;
for(int physicalPageIndex=1 ; physicalPageIndex<=reader.getNumberOfPages(); physicalPageIndex ++)
...
//Code to split PDF. Write each page to a separate pdf. For each pdf, insert all text inside `textList` onto the pdf
...
//Insert text
if(textList != null){
for(GenericText textComponent : textList){
String text = textComponent.generateText(physicalPageIndex, logicalPageIndex);
addText(text, cb, textComponent.getFont(), textComponent.getFontSize(), textComponent.getX(), textComponent.getY(), textComponent.getRotation());
}
}
}
...
}
所以在我的主类中我会这样做,
final String printName = printNameLookup.get(baseOutputName);
final String seq = config.getPrintJobSeq();
GenericText keyline = new GenericText(90, 640, 0, arial, 7, ComponentPlacement.FIRST_PAGE){
@Override
public String generateText(int physicalPage, int logicalPage) {
return printName + seq + " " + Utils.right(String.valueOf(logicalPage), 6, '0');
}
};
textList.add(keyline);
pdfProcess.splitPdf(inputPdfPath, true, textList, outputDir, baseOutputName, outputPdfName);
这工作很好,而且我认为它非常灵活,printName
和seq
已被声明为 final
以便在 generateText(intphysicalPage, int LogicalPage)
内传递。我如何设计它,以便它不需要 final
字段。 界面
有帮助吗?我使用guava API,我可以做这个
ImmutableListMultimap<String, File> groups = Multimaps.index(pdfList,
new Function<File, String>(){
public String apply(File input){
String[] ids = getId(input.getName());
PackageLog pl = logProcessor.lookUp(new Long(ids[0]), ids[1]);
String printName = printNameLookup.get(getPackageName(pl, s));
}
});
logProcessor
,并且printNameLookup
不是final
,我喜欢他们的方式设计,我现在正在阅读他们的资料,但这需要一些时间,任何具有设计知识的专家都可以给我一些启发吗?
I am trying to create an generic API that run on-top of iText. One of the function of this API is to allow the user to split the PDF to invidual page, and allow the user to add list of text onto each pdf page after the split. For example, a pdf of 20 pages, and after run this process, I will have 20 of 1-page-pdf, and the first pdf will have a text 000001 on it, and the last pdf will have 000020 on it pdf. So to accomplish this, I use abstract method that allow the developer to write code on how they want the text to format given the current page number.
public abstract class GenericText {
/**
* The X position of the text. (0, 0) is at the bottom left
*/
private float x;
/**
* The Y position of the text. (0, 0) is at the bottom left
*/
private float y;
/**
* The rotation of the text. Rotation 0, 90, 180, 270
*/
private float rotation;
/**
* <code>com.itextpdf.text.pdf.BaseFont</code>. Determine the font for the text
*/
private BaseFont font;
/**
* Determine the font size of the text
*/
private float fontSize;
/**
* This tells whether text can only be placed first page or on every page
*/
private ComponentPlacement placement;
/**
* 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);
...
}
PdfPrcessor.java: This is where the split happen
/**
* This is the main process that will split the pdf into individual page, and text to each page
*/
public void splitPdf(String inputPdf, boolean isSplit, List<GenericText> textList,
String outputDir, String baseOutputName, String outputPdfName) throws IOException, DocumentException{
...
PdfReader reader = new PdfReader(inputPdf)
PdfContentByte cb = ... ;
for(int physicalPageIndex=1 ; physicalPageIndex<=reader.getNumberOfPages(); physicalPageIndex ++)
...
//Code to split PDF. Write each page to a separate pdf. For each pdf, insert all text inside `textList` onto the pdf
...
//Insert text
if(textList != null){
for(GenericText textComponent : textList){
String text = textComponent.generateText(physicalPageIndex, logicalPageIndex);
addText(text, cb, textComponent.getFont(), textComponent.getFontSize(), textComponent.getX(), textComponent.getY(), textComponent.getRotation());
}
}
}
...
}
So in my main class I would do this,
final String printName = printNameLookup.get(baseOutputName);
final String seq = config.getPrintJobSeq();
GenericText keyline = new GenericText(90, 640, 0, arial, 7, ComponentPlacement.FIRST_PAGE){
@Override
public String generateText(int physicalPage, int logicalPage) {
return printName + seq + " " + Utils.right(String.valueOf(logicalPage), 6, '0');
}
};
textList.add(keyline);
pdfProcess.splitPdf(inputPdfPath, true, textList, outputDir, baseOutputName, outputPdfName);
This work great, and I think it is very flexible however, printName
and seq
has be be declared as final
in order to pass inside generateText(int physicalPage, int logicalPage)
. How do I design this so that it wont require final
field. Will interface
help? I use guava API, and I can do this
ImmutableListMultimap<String, File> groups = Multimaps.index(pdfList,
new Function<File, String>(){
public String apply(File input){
String[] ids = getId(input.getName());
PackageLog pl = logProcessor.lookUp(new Long(ids[0]), ids[1]);
String printName = printNameLookup.get(getPackageName(pl, s));
}
});
logProcessor
and printNameLookup
is not final
, I like the way they design, and I am reading their sources now, but it will take some times, anyone with expert on design knowledge can shed me some light?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将它们复制到最终变量中并使用它们。
或使用数组
Copy them into a final variables and use those instead.
or use arrays
您已经发现了模板方法设计模式。在这种情况下,将值复制到最终变量中就可以了。
You have discovered the Template Method design pattern. In this case copying the values into final variables will work.