工厂方法重载

时间:2018-04-25 21:58:15

标签: java overloading

我有一个子类列表,它们都是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);
    }
}

3 个答案:

答案 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