I implemented the (削除) Abstract (削除ここまで) Factory design pattern as follows.
Concrete Implementation
interface VideoExporter {
void exportVideo();
}
interface AudioExporter {
void exportAudio();
}
class HQVideoExporter implements VideoExporter {
@Override
public void exportVideo() {
System.out.println("Exporting HQ video");
}
}
class HQAudioExporter implements AudioExporter {
@Override
public void exportAudio() {
System.out.println("Exporting HQ Audio");
}
}
class LQVideoExporter implements VideoExporter {
@Override
public void exportVideo() {
System.out.println("Exporting LQ video");
}
}
class LQAudioExporter implements AudioExporter {
@Override
public void exportAudio() {
System.out.println("Exporting LQ Audio");
}
}
enum QUALITY_TYPE {
LOW, HIGH
}
Factory Class
class ExporterFactory {
static VideoExporter createVideoExporter(QUALITY_TYPE quality_type) {
return switch (quality_type) {
case LOW -> new LQVideoExporter();
case HIGH -> new HQVideoExporter();
};
}
static AudioExporter createAudioExporter(QUALITY_TYPE quality_type) {
return switch (quality_type) {
case LOW -> new LQAudioExporter();
case HIGH -> new HQAudioExporter();
};
}
}
Client code
VideoExporter videoExporter = ExporterFactory.createVideoExporter(QUALITY_TYPE.HIGH);
AudioExporter audioExporter = ExporterFactory.createAudioExporter(QUALITY_TYPE.LOW);
videoExporter.exportVideo();
audioExporter.exportAudio();
In the above implementation, createVideoExporter
and createAudioExporter
are exposed to the client code. I think this is not an abstract factory design pattern, it is just a factory design pattern. To make it an Abstract factory pattern do I need to create another interface with the concrete implementations returning similar kinds of codecs like only HQAudioExporter
and HQVideoExporter
can be created from one implementation, and LQVideoExporter
and LQAudioExporter
from another implementation, Am I correct?
3 Answers 3
This code looks fine, it is indeed an implementation of a factory pattern.
However, why would both Audio and Video be in the same factory? Apart from having the same responsibility to export something, they probably won't have much in common.
You already have two interfaces, you should also have two factories.
The original code is not an implementation of the Abstract Factory Pattern. The Abstract Factory Pattern would look a bit different:
interface AbstractExporterFactory {
VideoExporter createVideoExporter();
AudioExporter createAudioExporter();
}
class HQExporterFactory implements AbstractExporterFactory {
@Override
public VideoExporter createVideoExporter(){
return new HQVideoExporter();
}
@Override
public AudioExporter createAudioExporter(){
return new HQAudioExporter();
}
}
class LQExporterFactory implements AbstractExporterFactory {
@Override
public VideoExporter createVideoExporter(){
return new LQVideoExporter();
}
@Override
public AudioExporter createAudioExporter(){
return new LQAudioExporter();
}
}
The client just need to know AudioExporter
, VideoExporter
and AbstractExporterFactory
. Now for example UHQAudioExporter
, UHQVideoExporter
and corresponding UHQExporterFactory
can be used without changes to the rest of the code. I personally would also replace Exporter by Player, which would make more sense for some real life application.
The client code looks more like an example how the pattern should not be used, as mixing HQ and LQ objects should be prevented.
Abstract Factory Pattern helps in correctly creating the families of related products. Using ExporterFactory, one could create a combination of LQVideoExporter and HQAudioExporter which I believe is unsupported. If it is valid then you could have use Builder pattern where HIGH and LOW are value types of Audio and Video exporters. Also, Factory objects are self sufficient and don't need any input to decide which type of products are to be created.
Explore related questions
See similar questions with these tags.
enum QUALITY_TYPE
should beenum QualityType
to follow java-naming conventions \$\endgroup\$