就我个人而言,我从来没有理解工厂类的概念,因为直接实例化一个 Object 似乎更有用。我的问题很简单,在什么情况下使用工厂类模式是最好的选择,出于什么原因,一个好的工厂类是什么样的?
最佳答案
这是我的代码库中的一个真实的工厂。它用于生成一个采样器类,该类知道如何从某个数据集中采样数据(它最初是在 C# 中,所以请原谅任何 java 错误)
class SamplerFactory
{
private static Hashtable<SamplingType, ISampler> samplers;
static
{
samplers = new Hashtable<SamplingType, ISampler>();
samplers.put(SamplingType.Scalar, new ScalarSampler());
samplers.put(SamplingType.Vector, new VectorSampler());
samplers.put(SamplingType.Array, new ArraySampler());
}
public static ISampler GetSampler(SamplingType samplingType)
{
if (!samplers.containsKey(samplingType))
throw new IllegalArgumentException("Invalid sampling type or sampler not initialized");
return samplers.get(samplingType);
}
}
这是一个示例用法:
ISampler sampler = SamplerFactory.GetSampler(SamplingType.Array);
dataSet = sampler.Sample(dataSet);
如你所见,代码并不多,甚至可能更短、更快
ArraySampler sampler = new ArraySampler();
dataSet = sampler.Sample(dataSet);
比使用工厂。那我为什么还要打扰呢?嗯,有两个基本原因,相互依赖:
首先是代码的简单性和可维护性。假设在调用代码中,
enum
作为参数提供。 IE。如果我有需要处理数据的方法,包括采样,我可以写:void ProcessData(Object dataSet, SamplingType sampling) { //do something with data ISampler sampler = SamplerFactory.GetSampler(sampling); dataSet= sampler.Sample(dataSet); //do something other with data }
而不是像这样更麻烦的构造:
void ProcessData(Object dataSet, SamplingType sampling) { //do something with data ISampler sampler; switch (sampling) { case SamplingType.Scalar: sampler= new ScalarSampler(); break; case SamplingType.Vector: sampler= new VectorSampler(); break; case SamplingType.Array: sampler= new ArraySampler(); break; default: throw new IllegalArgumentException("Invalid sampling type"); } dataSet= sampler.Sample(dataSet); //do something other with data }
请注意,每次我需要采样时都应该编写这个怪物。您可以想象,如果我在
ScalarSampler
构造函数中添加了一个参数,或者添加了一个新的SamplingType
,那么进行更改将是多么有趣。而且这个工厂现在只有三个选项,想象一个有 20 个实现的工厂。第二,是代码的解耦。当我使用工厂时,调用代码不知道或不需要知道一个名为
ArraySampler
的类甚至存在。该类甚至可以在运行时解析,调用站点也不会更明智。因此,我可以随意更改ArraySampler
类,包括但不限于直接删除该类,例如我决定ScalarSampler
也应该用于数组数据。我只需要换行samplers.put(SamplingType.Array, new ArraySampler());
到
samplers.put(SamplingType.Array, new ScalarSampler());
它会神奇地工作。我不必更改调用类中的一行代码,这可能有数百个。实际上,工厂让我可以控制采样发生的内容和方式,并且任何采样更改都有效地封装在与系统其余部分接口(interface)的单个工厂类中。
关于java - 工厂类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14575457/