diff --git a/ProcessLib/Output/CreateOutput.cpp b/ProcessLib/Output/CreateOutput.cpp
index 2c11d520a0e8023be32fd47bbc111d520ec96627..119df26d4a0dc8ad631cd94ceb6b141cbd244f33 100644
--- a/ProcessLib/Output/CreateOutput.cpp
+++ b/ProcessLib/Output/CreateOutput.cpp
@@ -48,14 +48,29 @@ int convertVtkDataMode(std::string const& data_mode)
 namespace ProcessLib
 {
 std::unique_ptr<OutputFile> createOutputFile(
-    std::string&& output_directory, OutputType const output_type,
-    std::string&& prefix, std::string&& suffix, bool const compress_output,
-    unsigned int const number_of_files, std::string const& data_mode)
+    std::string const& output_directory, OutputType const output_type,
+    std::string&& prefix, std::string&& suffix, std::string const& data_mode,
+    bool const compress_output, unsigned int const number_of_files)
 {
-    return std::make_unique<OutputFile>(
-        std::move(output_directory), output_type, std::move(prefix),
-        std::move(suffix), convertVtkDataMode(data_mode), compress_output,
-        number_of_files);
+    if (output_type == OutputType::vtk)
+    {
+        return std::make_unique<OutputVtkFormat>(
+            output_directory, std::move(prefix), std::move(suffix),
+            convertVtkDataMode(data_mode), compress_output, number_of_files);
+    }
+    if (output_type == OutputType::xdmf)
+    {
+        return std::make_unique<OutputXDMFHDF5Format>(
+            output_directory, std::move(prefix), std::move(suffix),
+            convertVtkDataMode(data_mode), compress_output, number_of_files);
+    }
+    else
+    {
+        OGS_FATAL(
+            "No supported file type provided. Read `{:s}' from <output><type> \
+                in prj File. Supported: VTK, XDMF.",
+            output_type);
+    }
 }
 
 std::unique_ptr<Output> createOutput(
@@ -207,9 +222,9 @@ std::unique_ptr<Output> createOutput(
         //! \ogs_file_param{prj__time_loop__output__output_iteration_results}
         config.getConfigParameter<bool>("output_iteration_results", false);
 
-    OutputFile output_file(output_directory, output_type, prefix, suffix,
-                           convertVtkDataMode(data_mode), compress_output,
-                           number_of_files);
+    auto output_file = createOutputFile(
+        output_directory, output_type, std::move(prefix), std::move(suffix),
+        data_mode, compress_output, number_of_files);
 
     return std::make_unique<Output>(std::move(output_file),
                                     output_iteration_results,
diff --git a/ProcessLib/Output/Output.cpp b/ProcessLib/Output/Output.cpp
index 22d4af43be7921d7bd1a4063b1c26163429eb0c0..727b23be82045fd174b22742df38d7bc8ab37c5e 100644
--- a/ProcessLib/Output/Output.cpp
+++ b/ProcessLib/Output/Output.cpp
@@ -149,7 +149,7 @@ bool Output::isOutputProcess(const int process_id, const Process& process) const
            || is_last_process;
 }
 
-Output::Output(OutputFile&& output_file,
+Output::Output(std::unique_ptr<OutputFile> output_file,
                bool const output_nonlinear_iteration_results,
                OutputDataSpecification&& output_data_specification,
                std::vector<std::string>&& mesh_names_for_output,
@@ -171,7 +171,7 @@ void Output::addProcess(ProcessLib::Process const& process)
 
     for (auto const& mesh_output_name : _mesh_names_for_output)
     {
-        auto const filename = output_file.constructPVDName(mesh_output_name);
+        auto const filename = output_file->constructPVDName(mesh_output_name);
         _process_to_pvd_file.emplace(std::piecewise_construct,
                                      std::forward_as_tuple(&process),
                                      std::forward_as_tuple(filename));
@@ -183,21 +183,22 @@ void Output::outputMeshes(
     const double t, const int iteration,
     std::vector<std::reference_wrapper<const MeshLib::Mesh>> meshes)
 {
-    if (output_file.type == ProcessLib::OutputType::vtk)
+    if (output_file->type == ProcessLib::OutputType::vtk)
     {
         for (auto const& mesh : meshes)
         {
             auto const filename =
-                output_file.constructPVDName(mesh.get().getName());
+                output_file->constructPVDName(mesh.get().getName());
             auto& pvd_file = findPVDFile(process, process_id, filename,
                                          _process_to_pvd_file);
-            outputMeshVtk(output_file, pvd_file, mesh, t, timestep, iteration);
+            outputMeshVtk(*output_file.get(), pvd_file, mesh, t, timestep,
+                          iteration);
         }
     }
-    else if (output_file.type == ProcessLib::OutputType::xdmf)
+    else if (output_file->type == ProcessLib::OutputType::xdmf)
     {
-        output_file.outputMeshXdmf(_output_data_specification.output_variables,
-                                   std::move(meshes), timestep, t, iteration);
+        output_file->outputMeshXdmf(_output_data_specification.output_variables,
+                                    std::move(meshes), timestep, t, iteration);
     }
 }
 
@@ -301,7 +302,7 @@ void Output::doOutput(Process const& process,
     // Note: last time step may be output twice: here and in
     // doOutputLastTimestep() which throws a warning.
     InSituLib::CoProcess(process.getMesh(), t, timestep, false,
-                         output_file.directory);
+                         output_file->directory);
 #endif
 }
 
@@ -318,7 +319,7 @@ void Output::doOutputLastTimestep(Process const& process,
     }
 #ifdef USE_INSITU
     InSituLib::CoProcess(process.getMesh(), t, timestep, true,
-                         output_file.directory);
+                         output_file->directory);
 #endif
 }
 
@@ -348,15 +349,15 @@ void Output::doOutputNonlinearIteration(Process const& process,
         return;
     }
 
-    std::string const output_file_name = output_file.constructFilename(
+    std::string const output_file_name = output_file->constructFilename(
         process.getMesh().getName(), timestep, t, iteration);
 
     std::string const output_file_path =
-        BaseLib::joinPaths(output_file.directory, output_file_name);
+        BaseLib::joinPaths(output_file->directory, output_file_name);
 
     DBUG("output iteration results to {:s}", output_file_path);
-    outputMeshVtk(output_file_path, process.getMesh(), output_file.compression,
-                  output_file.data_mode);
+    outputMeshVtk(output_file_path, process.getMesh(), output_file->compression,
+                  output_file->data_mode);
     INFO("[time] Output took {:g} s.", time_output.elapsed());
 }
 }  // namespace ProcessLib
diff --git a/ProcessLib/Output/Output.h b/ProcessLib/Output/Output.h
index 748828c47cf1dd5ba3b850fd5394332816526531..211a01ffc159b57a521b4ccab17c000494db8c2b 100644
--- a/ProcessLib/Output/Output.h
+++ b/ProcessLib/Output/Output.h
@@ -32,7 +32,7 @@ class Process;
 class Output
 {
 public:
-    Output(OutputFile&& output_file,
+    Output(std::unique_ptr<OutputFile> output_file,
            bool const output_nonlinear_iteration_results,
            OutputDataSpecification&& output_data_specification,
            std::vector<std::string>&& mesh_names_for_output,
@@ -93,7 +93,7 @@ private:
         const int process_id, double const t,
         std::vector<GlobalVector*> const& xs) const;
 
-    OutputFile output_file;
+    std::unique_ptr<OutputFile> output_file;
 
     bool const _output_nonlinear_iteration_results;
 
diff --git a/ProcessLib/Output/OutputFile.cpp b/ProcessLib/Output/OutputFile.cpp
index 4cfb64b79b572c11ed2fcdfb115f3cf0e1234164..24dffcf8105efb3253b535ca66f1272b07e9d8c9 100644
--- a/ProcessLib/Output/OutputFile.cpp
+++ b/ProcessLib/Output/OutputFile.cpp
@@ -83,30 +83,26 @@ OutputFile::OutputFile(std::string const& directory, OutputType const type,
 {
 }
 
-std::string OutputFile::constructFilename(std::string mesh_name,
-                                          int const timestep,
-                                          double const t,
-                                          int const iteration) const
+std::string OutputVtkFormat::constructFilename(std::string mesh_name,
+                                               int const timestep,
+                                               double const t,
+                                               int const iteration) const
 {
-    std::map<OutputType, std::string> filetype_to_extension = {
-        {OutputType::vtk, "vtu"}, {OutputType::xdmf, "xdmf"}};
+    return BaseLib::constructFormattedFileName(prefix, mesh_name, timestep, t,
+                                               iteration) +
+           BaseLib::constructFormattedFileName(suffix, mesh_name, timestep, t,
+                                               iteration) +
+           ".vtu";
+}
 
-    try
-    {
-        std::string extension = filetype_to_extension.at(type);
-        return BaseLib::constructFormattedFileName(prefix, mesh_name, timestep,
-                                                   t, iteration) +
-               BaseLib::constructFormattedFileName(suffix, mesh_name, timestep,
-                                                   t, iteration) +
-               "." + extension;
-    }
-    catch (std::out_of_range&)
-    {
-        OGS_FATAL(
-            "No supported file type provided. Read `{:s}' from <output><type> \
-                in prj file. Supported: VTK, XDMF.",
-            type);
-    }
+std::string OutputXDMFHDF5Format::constructFilename(std::string mesh_name,
+                                                    int const timestep,
+                                                    double const t,
+                                                    int const iteration) const
+{
+    return BaseLib::constructFormattedFileName(prefix, mesh_name, timestep, t,
+                                               iteration) +
+           ".xdmf";
 }
 
 void OutputFile::outputMeshXdmf(
diff --git a/ProcessLib/Output/OutputFile.h b/ProcessLib/Output/OutputFile.h
index bc74d335675083f93d3ff321701672bdbb3ea4d4..bcf49c479dc29997d1ced36cc539fc60fe873504 100644
--- a/ProcessLib/Output/OutputFile.h
+++ b/ProcessLib/Output/OutputFile.h
@@ -29,6 +29,7 @@ struct OutputFile
                std::string const& prefix, std::string const& suffix,
                int const data_mode_, bool const compression_,
                unsigned int const n_files);
+    virtual ~OutputFile() = default;
 
     std::string directory;
     std::string prefix;
@@ -48,8 +49,9 @@ struct OutputFile
     //! Specifies the number of hdf5 output files.
     unsigned int const n_files;
 
-    std::string constructFilename(std::string mesh_name, int const timestep,
-                                  double const t, int const iteration) const;
+    virtual std::string constructFilename(std::string mesh_name,
+                                          int const timestep, double const t,
+                                          int const iteration) const = 0;
 
     void outputMeshXdmf(
         std::set<std::string> const& output_variables,
@@ -59,6 +61,48 @@ struct OutputFile
     std::string constructPVDName(std::string const& mesh_name) const;
 };
 
+struct OutputVtkFormat final : public OutputFile
+{
+    OutputVtkFormat(std::string const& directory, std::string const& prefix,
+                    std::string const& suffix, int const data_mode,
+                    bool const compression, const int number_of_files)
+        : OutputFile(directory, OutputType::vtk, prefix, suffix, data_mode,
+                     compression, number_of_files)
+    {
+    }
+
+    //! Chooses vtk's data mode for output following the enumeration given
+    /// in the vtkXMLWriter: {Ascii, Binary, Appended}.  See vtkXMLWriter
+    /// documentation
+    /// http://www.vtk.org/doc/nightly/html/classvtkXMLWriter.html
+    // int const data_mode;
+
+    //! Enables or disables zlib-compression of the output files.
+    // bool const compression;
+
+    std::string constructFilename(std::string mesh_name, int const timestep,
+                                  double const t,
+                                  int const iteration) const override;
+
+    // std::string constructPVDName(std::string const& mesh_name) const;
+};
+
+struct OutputXDMFHDF5Format final : public OutputFile
+{
+    OutputXDMFHDF5Format(std::string const& directory,
+                         std::string const& prefix, std::string const& suffix,
+                         int const data_mode, bool const compression,
+                         unsigned int const n_files)
+        : OutputFile(directory, OutputType::xdmf, prefix, suffix, data_mode,
+                     compression, n_files)
+    {
+    }
+
+    std::string constructFilename(std::string mesh_name, int const timestep,
+                                  double const t,
+                                  int const iteration) const override;
+};
+
 void outputMeshVtk(std::string const& file_name, MeshLib::Mesh const& mesh,
                    bool const compress_output, int const data_mode);
 }  // namespace ProcessLib