Java 工厂方法重载

Java 工厂方法重载,java,overloading,Java,Overloading,我有一个子类列表,这些子类都是超类的实例。 我的目标是创建一个工厂,它将根据子类返回不同的结果 public class SuperClass { ... } public class SubClass1 extends SuperClass { ... } public class SubClass2 extends SuperClass { ... } public class Factory { public static getInstance(Su

我有一个子类列表,这些子类都是超类的实例。 我的目标是创建一个工厂,它将根据子类返回不同的结果

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();
公共类超类{
...
}
公共类子类1扩展了超类{
...
}
公共类子类2扩展了超类{
...
}
公营工厂{
公共静态getInstance(子类1项){
返回新的EditText();
}
公共静态getInstance(子类2项){
返回新复选框();
}
}
公共类生成器{
公共生成器(){
List=getList();
对于(超类项:列表){
Factory.getInstance(项目);
}
}
List getList(){
...
}
}
新发电机();
这段代码在编译过程中会失败,因为它需要getInstance(超类项)重载,但如果我添加它,它将始终被调用

有没有一种方法可以在不涉及超类、子类1、子类2的情况下做到这一点

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);
    }
}
导入android.content.Context;
导入android.view.view;
导入android.widget.CheckBox;
导入android.widget.EditText;
导入android.widget.RadioButton;
导入com.tom_roush.pdfbox.cos.COSArray;
导入com.tom_roush.pdfbox.cos.cosdirectionary;
导入com.tom_roush.pdfbox.cos.COSName;
导入com.tom_roush.pdfbox.pdmodel.PDDocument;
导入com.tom_roush.pdfbox.pdmodel.PDDocumentCatalog;
导入com.tom_roush.pdfbox.pdmodel.PDPage;
导入com.tom_roush.pdfbox.pdmodel.PDPageTree;
导入com.tom_roush.pdfbox.pdmodel.common.PDRectangle;
导入com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
导入com.tom_roush.pdfbox.pdmodel.interactive.form.PDAcroForm;
导入com.tom_roush.pdfbox.pdmodel.interactive.form.PDCheckbox;
导入com.tom_roush.pdfbox.pdmodel.interactive.form.PDField;
导入com.tom_roush.pdfbox.pdmodel.interactive.form.PDRadioButton;
导入com.tom_roush.pdfbox.pdmodel.interactive.form.PDTextField;
公共类页面{
私人视野;
私人语境;
私人文件档案;
公共页面(上下文-上下文、视图-视图、PDDocument-文档){
视图=_视图;
上下文=_上下文;
文件=_文件;
renderFields();
}
私有void renderFields(){
PDDocumentCatalog docCatalog=document.getDocumentCatalog();
RelativeLayout ll=view.findViewById(R.id.pageFields);
ll.removeAllViews();
PDPageTree pageTree=docCatalog.getPages();
PDPage=pageTree.get(pageIndex);
PDAcroForm acroForm=docCatalog.getAcroForm();
列表字段=acroForm.getFields();
用于(PDField:字段){
字符串fieldName=field.getFullyQualifiedName();
COSDictionary fieldDict=field.getCOSObject();
COSArray fieldAreaArray=(COSArray)fieldDict.getDictionaryObject(COSName.RECT);
PDRectangle mediaBox=新的PDRectangle(fieldAreaArray);
int fieldColor=Color.argb(180220228254);
//工厂
View fieldView=FieldFactory.getViewFromPDField(上下文,字段);
RelativeLayout.LayoutParams fieldLayoutParams=新的RelativeLayout.LayoutParams(
(int)(mediaBox.getWidth()*posRatio),
(int)(mediaBox.getHeight()*posRatio)
);
fieldLayoutParams.addRule(RelativeLayout.ALIGN\u PARENT\u LEFT);
fieldLayoutParams.leftMargin=(int)(左*正比例);
fieldLayoutParams.topMargin=(int)(top*posRatio);
fieldView.setBackgroundColor(fieldColor);
fieldView.setLayoutParams(fieldLayoutParams);
ll.addView(fieldView,fieldLayoutParams);
}
}
}
...
公营工厂{
公共静态视图getViewFromPDField(上下文,PDTextField){
返回新的编辑文本(上下文);
}
公共静态视图getViewFromPDField(上下文上下文,PDCheckbox字段){
返回新复选框(上下文);
}
公共静态视图getViewFromPDField(上下文上下文,PDRadioButton字段){
返回新单选按钮(上下文);
}
}

相反,将
超类
抽象化,并添加一个新的实例方法,该方法实现您所寻找的功能,每个子类用其不同的行为覆盖它:

public abstract class SuperClass {
    public abstract View getView(Context context);
}
public class SubClass1 extends SuperClass {
    @Override
    public View getView(Context 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);
        }
    }
}
您可以按如下方式实现factory:

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);
        }
    }
}
当然,这只是一个示例,您应该使用一些反射库或UTIL更好地实现它。我们假设每个
视图
实现都提供了构造函数等。

我喜欢的是的解决方案,并希望使用扩展它

使用泛型背后的理由是要有一个单一的、通用的实现,以后可以用于多种任务

我已将原来的解决方案修改为通用解决方案。工厂现在必须实例化,因为它是泛型的,实例化为我们选择的特定类提供了特定工厂

为了编译和运行以下代码,我使用了我的选择:

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));
        }
    }
}

如果
子类3
,该怎么办?公共静态getInstance(…)-这甚至可以编译吗?返回类型如何?使用泛型如何?允许您以面向对象的方式执行此操作,但这涉及到触摸
超类
和所有子类。否则,它意味着在
Generator()
中使用
instanceof
测试类型,使用一系列
if
条件和强制类型转换。@JamesB很抱歉,我没有尝试编译这个确切的代码,但我的代码类似。我只是提出了一个使用反射的想法。我不想把事情复杂化
TextBox
CheckBox
TextBox