gpt4 book ai didi

java - 工厂方法重载

转载 作者:行者123 更新时间:2023-11-30 07:47:13 30 4
gpt4 key购买 nike

我有一个子类列表,它们都是父类(super class)的实例。我的目标是创建一个工厂,它将根据子类返回不同的结果。

public class SuperClass {
...
}

public class SubClass1 extends SuperClass {
...
}

public class SubClass2 extends SuperClass {
...
}

public class Factory {
public static getInstance(SubClass1 item) {
return new EditText();
}

public static getInstance(SubClass2 item) {
return new CheckBox();
}
}

public class Generator {
public Generator() {
List<SuperClass> list = getList();

for (SuperClass item : list) {
Factory.getInstance(item);
}
}

List<SuperClass> getList() {
...
}
}

new Generator();

此代码在编译过程中会失败,因为它需要 getInstance(SuperClass item) 重载,但如果我添加它,它将始终被调用。

有没有办法在不触及 SuperClass、SubClass1、SubClass2 的情况下做到这一点?

更新。这里为了说明我要存档的是原代码:

import android.content.Context;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;

import com.tom_roush.pdfbox.cos.COSArray;
import com.tom_roush.pdfbox.cos.COSDictionary;
import com.tom_roush.pdfbox.cos.COSName;
import com.tom_roush.pdfbox.pdmodel.PDDocument;
import com.tom_roush.pdfbox.pdmodel.PDDocumentCatalog;
import com.tom_roush.pdfbox.pdmodel.PDPage;
import com.tom_roush.pdfbox.pdmodel.PDPageTree;
import com.tom_roush.pdfbox.pdmodel.common.PDRectangle;
import com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import com.tom_roush.pdfbox.pdmodel.interactive.form.PDAcroForm;
import com.tom_roush.pdfbox.pdmodel.interactive.form.PDCheckbox;
import com.tom_roush.pdfbox.pdmodel.interactive.form.PDField;
import com.tom_roush.pdfbox.pdmodel.interactive.form.PDRadioButton;
import com.tom_roush.pdfbox.pdmodel.interactive.form.PDTextField;


public class Page {
private View view;
private Context context;
private PDDocument file;

public Page(Context _context, View _view, PDDocument _document) {
view = _view;
context = _context;
document = _document;

renderFields();
}

private void renderFields() {
PDDocumentCatalog docCatalog = document.getDocumentCatalog();
RelativeLayout ll = view.findViewById(R.id.pageFields);
ll.removeAllViews();

PDPageTree pageTree = docCatalog.getPages();
PDPage page = pageTree.get(pageIndex);

PDAcroForm acroForm = docCatalog.getAcroForm();
List<PDField> fields = acroForm.getFields();

for (PDField field : fields) {
String fieldName = field.getFullyQualifiedName();
COSDictionary fieldDict = field.getCOSObject();

COSArray fieldAreaArray = (COSArray) fieldDict.getDictionaryObject(COSName.RECT);
PDRectangle mediaBox = new PDRectangle(fieldAreaArray);

int fieldColor = Color.argb(180, 220, 228, 254);
// Factory
View fieldView = FieldFactory.getViewFromPDField(context, field);
RelativeLayout.LayoutParams fieldLayoutParams = new RelativeLayout.LayoutParams(
(int) (mediaBox.getWidth() * posRatio),
(int) (mediaBox.getHeight() * posRatio)
);
fieldLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
fieldLayoutParams.leftMargin = (int) (left * posRatio);
fieldLayoutParams.topMargin = (int) (top * posRatio);
fieldView.setBackgroundColor(fieldColor);
fieldView.setLayoutParams(fieldLayoutParams);

ll.addView(fieldView, fieldLayoutParams);
}
}
}

...

public class FieldFactory {
public static View getViewFromPDField(Context context, PDTextField field) {
return new EditText(context);
}

public static View getViewFromPDField(Context context, PDCheckbox field) {
return new CheckBox(context);
}

public static View getViewFromPDField(Context context, PDRadioButton field) {
return new RadioButton(context);
}
}

最佳答案

不幸的是,没有干净的方法来做到这一点,因为在编译期间我们不知道要调用哪个方法。为此,您可以使用 instanceof 关键字或使用反射。

假设您的模型大致如下所示:

class SuperClass {
//...
}

class SubClass1 extends SuperClass {
//...
}

class SubClass2 extends SuperClass {
//...
}

class Context {
//...
}

abstract class View {
private final Context context;

public View(Context context) {
this.context = context;
}

@Override
public String toString() {
return getClass().getSimpleName();
}
}

class TextBox extends View {

public TextBox(Context context) {
super(context);
}
}

class CheckBox extends View {

public CheckBox(Context context) {
super(context);
}
}

你可以像下面这样实现工厂:

class FieldFactory {
static Map<Class<? extends SuperClass>, Class<? extends View>> fieldEditorMap = new HashMap<>();

static {
fieldEditorMap.put(SubClass1.class, TextBox.class);
fieldEditorMap.put(SubClass2.class, CheckBox.class);
}

public static View getViewFromPDField(Context context, SuperClass field) {
Class<? extends View> editorClass = fieldEditorMap.get(field.getClass());
try {
return editorClass.getConstructor(Context.class).newInstance(context);
} catch (Exception e) {
throw new IllegalArgumentException("Can not create view for " + field.getClass().getSimpleName(), e);
}
}
}

示例用法:

public class Main {

public static void main(String[] args) throws Exception {
List<SuperClass> fields = Arrays.asList(new SubClass1(), new SubClass2(), new SubClass1());
for (SuperClass field : fields) {
System.out.println(FieldFactory.getViewFromPDField(new Context(), field));
}
}
}

以上打印:

TextBox
CheckBox
TextBox

当然这只是一个示例,您应该使用一些反射库或实用程序更好地实现它。我们假设每个 View 实现都有给定的构造函数等。

关于java - 工厂方法重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50031934/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com