我有一个子类列表,它们都是Super类的实例。 我的目标是创建一个工厂,它将根据子类返回不同的结果。
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的情况下执行此操作?
UPD。为了澄清我想要存档的内容,原始代码是:
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);
}
}
答案 0 :(得分:1)
而是使while((len = ngetline(line, MAXLENGTH)) > 0)
抽象化并添加一个新的实例方法来执行您正在寻找的内容,每个子类用其不同的行为覆盖它:
SuperClass
答案 1 :(得分:1)
不幸的是,没有干净的方法可以做到这一点,因为在编译期间我们不知道要调用哪个方法。为此,您可以使用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
当然这只是一个例子,您应该使用一些Reflection库或utils更好地实现它。我们假设每个View
实现都给出了构造函数等。
答案 2 :(得分:1)
我喜欢Michał Ziober的解决方案,并希望使用java generics来消费它。
使用泛型的原因是有一个通用的实现,以后可以用于多种任务。
我已将原始解决方案修改为通用解决方案。现在必须实例化工厂,因为它是通用的,并且实例化为我们提供了针对我们选择的特定类的特定工厂。
我使用了我的online java compiler选项来编译并运行以下代码:
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public class MyClass {
static class SuperClass {
//tagging
}
static class SubClass1 extends SuperClass {
//
}
static class SubClass2 extends SuperClass {
//...
}
static class Context {
//...
}
static abstract class View {
private final Context context;
public View(Context context) {
this.context = context;
}
@Override
public String toString() {
return getClass().getSimpleName();
}
}
static class TextBox extends View {
public TextBox(Context context) {
super(context);
}
}
static class CheckBox extends View {
public CheckBox(Context context) {
super(context);
}
}
static class Pair<P0,P1> {
public P0 p0;
public P1 p1;
public Pair(P0 p0, P1 p1) {
this.p0 = p0;
this.p1 = p1;
}
}
static class FieldFactory<T extends SuperClass, P extends View> {
Map<Class<T>, Class<P>> fieldEditorMap = new HashMap<>();
public FieldFactory(List<Pair<Class<T>, Class<P>>> boundClassMapping){
boundClassMapping.stream().forEach(pair -> fieldEditorMap.put(pair.p0,pair.p1));
}
public P getViewFromPDField(Context context, T field) {
Class<P> 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 static void main(String args[]) {
List<Pair<Class<? extends SuperClass>, Class<? extends View>>> mapping = new ArrayList<>();
mapping.add(new Pair<Class<? extends SuperClass>, Class<? extends View>>(SubClass1.class, TextBox.class));
mapping.add(new Pair<Class<? extends SuperClass>, Class<? extends View>>(SubClass2.class, CheckBox.class));
FieldFactory ff = new FieldFactory(mapping);
List<SuperClass> fields = Arrays.asList(new SubClass1(), new SubClass2(), new SubClass1());
for (SuperClass field : fields) {
System.out.println(ff.getViewFromPDField(new Context(), field));
}
}
}
关于产出:
TextBox
CheckBox
TextBox