我有几个类处理不同的文件扩展名。他们都实现了一个通用接口或扩展相同的抽象类。我想根据文件的扩展名动态地(运行时)获取正确的子类。
现在我有点卡在哪里放置逻辑来选择正确的实现。 在思考了一下之后,我现在将在父类中创建一个dict来进行选择。 e.g。
{"jpg": jpgProcessor,
"gif": gifProcessor}.get(fileExt)().process(file)
在Java中,我将在parentClass中创建一个寄存器方法,该方法由子类的静态块调用。然后,parentClass将有一个getFilter(String fileExt)方法,该方法从HashMap或类似的东西中选择正确的类。
问题:
奖金:
我总是阅读很多关于工厂,抽象工厂模式的文章但很不确定我是否可以替换父类中的类型检查。
答案 0 :(得分:2)
在Java中,使用enum
。让我们使用jpg
和gif
来举例说明您的上述示例。让我们假设我们有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 在示例中,按文件替换货币,按文件扩展名替换货币符号。