根据变量选择实现(类)

时间:2015-02-19 08:50:30

标签: java python design-patterns

我有几个类处理不同的文件扩展名。他们都实现了一个通用接口或扩展相同的抽象类。我想根据文件的扩展名动态地(运行时)获取正确的子类。

现在我有点卡在哪里放置逻辑来选择正确的实现。 在思考了一下之后,我现在将在父类中创建一个dict来进行选择。 e.g。

{"jpg": jpgProcessor,
"gif": gifProcessor}.get(fileExt)().process(file)

在Java中,我将在parentClass中创建一个寄存器方法,该方法由子类的静态块调用。然后,parentClass将有一个getFilter(String fileExt)方法,该方法从HashMap或类似的东西中选择正确的类。

问题:

  • 有没有更好的方法在Python中实现这样的东西?

奖金:

  • 这是否有具体的模式?怎么称呼?
  • 这是用Java实现这个的正确方法吗?

我总是阅读很多关于工厂,抽象工厂模式的文章但很不确定我是否可以替换父类中的类型检查。

3 个答案:

答案 0 :(得分:2)

在Java中,使用enum。让我们使用jpggif来举例说明您的上述示例。让我们假设我们有3个类:

class Processor {}
class JpgProcessor extends Processor {}
class GifProcessor extends Processor {}

我们现在可以使用enum工厂模式来创建实例:

enum ProcessorFactory implements Supplier<Processor> {
    JPG("jpg", JpgProcessor::new),
    GIF("gif", GifProcessor::new);

    private static final ProcessorFactory[] VALUES = values();
    private final String extension;
    private final Supplier<? extends Processor> supplier;


    private ProcessorFactory(String extension, Supplier<? extends Processor> supplier) {
        this.extension = extension;
        this.supplier = supplier;
    }

    public static ProcessorFactory fromExtension(final String extension) {
        return Arrays.stream(VALUES)
                .filter(v -> v.extension.equals(extension))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("Invalid extension " + extension + "."));
    }

    @Override
    public Processor get() {
        return supplier.get();
    }
}

这里有很多事情要发生。首先,enum implements Supplier<Processor>表示您可以使用它来获取Processor实例,如下所示:

final Processor jpgProcessor = ProcessorFactory.JPG.get(); 

接下来,每个enum都有String extension,这些用于将特定enum实例绑定到特定扩展名。方法fromExtension执行此操作,因此您可以使用以下方法获取正确的值:

final ProcessorFactory factory = ProcessorFactory.fromExtension("jpg");

因此,要从扩展程序中获取Processor,您需要做的就是:

final Processor jpgProcessor = ProcessorFactory.fromExtension("jpg").get(); 

这假设每次互动都需要new Processor()。如果您不需要,那么简单的Map<String, Processor>也可以正常工作:

final Map<String, Processor> map = new HashMap<>();
map.put("jpg", new JpgProcessor());
map.put("gif", new GifProcessor());

获得处理器:

final Processor processor = map.get("jpg");

答案 1 :(得分:1)

我不了解Java ......在 python 中,我可能会这样做:

class ProcessorSelector(object):
    def __init__(self):
        self._processor_map = {}

    def register(self, type, processor):
        # type checking goes here if you're worried about it...
        # e.g. `if not isinstance(processor, Processor): raise TypeError`
        self._processor_map[type] = processor

    def select(self, type):
        return self._processor_pam[type]

selector = ProcessorSelector()
selector.register('jpg', JpgProcessor)
cls = selector.select('jpg')
processor = cls()
processor.process(file)

当然,您根本不需要 ProcessorSelector类......您可以使用常规词典: - )。

答案 2 :(得分:0)

您可以使用方法工厂模式。看这里的例子: http://javarevisited.blogspot.se/2011/12/factory-design-pattern-java-example.html 在示例中,按文件替换货币,按文件扩展名替换货币符号。