diff --git a/Core/Multilayer/DecouplingApproximationStrategy.cpp b/Core/Multilayer/DecouplingApproximationStrategy.cpp
index af67ad404e2bb89dd7ff088880ccda7336a7298f..86cce6ffbee0e0404441a3575c6feca88ec6500a 100644
--- a/Core/Multilayer/DecouplingApproximationStrategy.cpp
+++ b/Core/Multilayer/DecouplingApproximationStrategy.cpp
@@ -30,8 +30,9 @@ double DecouplingApproximationStrategy1::evaluateForList(
 {
     double intensity = 0.0;
     complex_t amplitude = complex_t(0.0, 0.0);
+    auto precomputed_ff = precomputeScalar(sim_element, m_formfactor_wrappers);
     for (size_t i = 0; i < m_formfactor_wrappers.size(); ++i) {
-        complex_t ff = m_precomputed_ff1[i];
+        complex_t ff = precomputed_ff[i];
         if (std::isnan(ff.real()))
             throw Exceptions::RuntimeErrorException(
                 "DecouplingApproximationStrategy::evaluateForList() -> Error! Amplitude is NaN");
@@ -55,8 +56,9 @@ double DecouplingApproximationStrategy2::evaluateForList(
     Eigen::Matrix2cd mean_intensity = Eigen::Matrix2cd::Zero();
     Eigen::Matrix2cd mean_amplitude = Eigen::Matrix2cd::Zero();
 
+    auto precomputed_ff = precomputePolarized(sim_element, m_formfactor_wrappers);
     for (size_t i = 0; i < m_formfactor_wrappers.size(); ++i) {
-        Eigen::Matrix2cd ff = m_precomputed_ff2[i];
+        Eigen::Matrix2cd ff = precomputed_ff[i];
         if (!ff.allFinite())
             throw Exceptions::RuntimeErrorException(
                 "DecouplingApproximationStrategy::evaluateForList() -> "
diff --git a/Core/Multilayer/DecouplingApproximationStrategy.h b/Core/Multilayer/DecouplingApproximationStrategy.h
index 951b97b37238303863a74cd9202039ac97b423a4..d44308a162ed35eb9bd23ea5b494db6a9365bad0 100644
--- a/Core/Multilayer/DecouplingApproximationStrategy.h
+++ b/Core/Multilayer/DecouplingApproximationStrategy.h
@@ -25,14 +25,13 @@ class SimulationElement;
 //! in decoupling approximation.
 //! @ingroup algorithms_internal
 
-class BA_CORE_API_ DecouplingApproximationStrategy1 final
-    : public IInterferenceFunctionStrategy1
+class DecouplingApproximationStrategy1 final : public IInterferenceFunctionStrategy
 {
 public:
     DecouplingApproximationStrategy1(SimulationOptions sim_params)
-        : IInterferenceFunctionStrategy1(sim_params) {}
+        : IInterferenceFunctionStrategy(sim_params) {}
 
-private:
+protected:
     double evaluateForList(const SimulationElement& sim_element) const override;
 };
 
@@ -40,14 +39,13 @@ private:
 //! in decoupling approximation.
 //! @ingroup algorithms_internal
 
-class BA_CORE_API_ DecouplingApproximationStrategy2 final
-    : public IInterferenceFunctionStrategy2
+class DecouplingApproximationStrategy2 final : public IInterferenceFunctionStrategy
 {
 public:
     DecouplingApproximationStrategy2(SimulationOptions sim_params)
-        : IInterferenceFunctionStrategy2(sim_params) {}
+        : IInterferenceFunctionStrategy(sim_params) {}
 
-private:
+protected:
     double evaluateForList(const SimulationElement& sim_element) const override;
 };
 
diff --git a/Core/Multilayer/IInterferenceFunctionStrategy.cpp b/Core/Multilayer/IInterferenceFunctionStrategy.cpp
index b0ad2b714f74d1cac07766ab42849a16387640b6..f723c898c1383f5342f2045f80f28f364fdbba70 100644
--- a/Core/Multilayer/IInterferenceFunctionStrategy.cpp
+++ b/Core/Multilayer/IInterferenceFunctionStrategy.cpp
@@ -3,8 +3,7 @@
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
 //! @file      Core/Multilayer/IInterferenceFunctionStrategy.cpp
-//! @brief     Implements default behaviour of IInterferenceFunctionStrategy,
-//!              IInterferenceFunctionStrategy1, IInterferenceFunctionStrategy2
+//! @brief     Implements default behaviour of IInterferenceFunctionStrategy.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -43,7 +42,8 @@ void IInterferenceFunctionStrategy::init(
     const IInterferenceFunction* p_iff)
 {
     if (weighted_formfactors.size()==0)
-        throw Exceptions::ClassInitializationException("Bug: Decorated layer has no formfactors.");
+        throw Exceptions::ClassInitializationException(
+                "IInterferenceFunctionStrategy::init: strategy gets no formfactors.");
     m_formfactor_wrappers = weighted_formfactors;
     if (p_iff)
         mP_iff.reset(p_iff->clone());
@@ -57,10 +57,32 @@ double IInterferenceFunctionStrategy::evaluate(const SimulationElement& sim_elem
 {
     if (m_options.isIntegrate() && (sim_element.getSolidAngle() > 0.0))
         return MCIntegratedEvaluate(sim_element);
-    precomputeParticleFormfactors(sim_element);
     return evaluateForList(sim_element);
 }
 
+std::vector<complex_t> IInterferenceFunctionStrategy::precomputeScalar(
+        const SimulationElement& sim_element,
+        const SafePointerVector<FormFactorCoherentSum>& ff_wrappers)
+{
+    std::vector<complex_t> result;
+    for (auto ffw: ff_wrappers) {
+        result.push_back(ffw->evaluate(sim_element));
+    }
+    return result;
+}
+
+IInterferenceFunctionStrategy::matrixFFVector_t
+IInterferenceFunctionStrategy::precomputePolarized(
+        const SimulationElement& sim_element,
+        const SafePointerVector<FormFactorCoherentSum>& ff_wrappers)
+{
+    matrixFFVector_t result;
+    for (auto ffw: ff_wrappers) {
+        result.push_back(ffw->evaluatePol(sim_element));
+    }
+    return result;
+}
+
 //! Performs a Monte Carlo integration over the bin for the evaluation of the intensity.
 double IInterferenceFunctionStrategy::MCIntegratedEvaluate(
     const SimulationElement& sim_element) const
@@ -80,37 +102,5 @@ double IInterferenceFunctionStrategy::evaluate_for_fixed_angles(
     SimulationElement* pars = static_cast<SimulationElement*>(params);
 
     SimulationElement sim_element(*pars, par0, par1);
-    precomputeParticleFormfactors(sim_element);
     return pars->getIntegrationFactor(par0, par1) * evaluateForList(sim_element);
 }
-
-
-IInterferenceFunctionStrategy1::IInterferenceFunctionStrategy1(
-        const SimulationOptions& sim_params)
-    : IInterferenceFunctionStrategy(sim_params)
-{}
-
-//! Precomputes scalar form factors.
-void IInterferenceFunctionStrategy1::precomputeParticleFormfactors(
-    const SimulationElement& sim_element) const
-{
-    m_precomputed_ff1.clear();
-    for (auto ffw: m_formfactor_wrappers) {
-        m_precomputed_ff1.push_back(ffw->evaluate(sim_element));
-    }
-}
-
-IInterferenceFunctionStrategy2::IInterferenceFunctionStrategy2(
-        const SimulationOptions& sim_params)
-    : IInterferenceFunctionStrategy(sim_params)
-{}
-
-//! Precomputes matrix form factors.
-void IInterferenceFunctionStrategy2::precomputeParticleFormfactors(
-    const SimulationElement& sim_element) const
-{
-    m_precomputed_ff2.clear();
-    for (auto ffw: m_formfactor_wrappers) {
-        m_precomputed_ff2.push_back(ffw->evaluatePol(sim_element));
-    }
-}
diff --git a/Core/Multilayer/IInterferenceFunctionStrategy.h b/Core/Multilayer/IInterferenceFunctionStrategy.h
index 13871ec2790511cdd34f1a250da88d7975cca050..485ea9ecc652e8376c6658780e479ee698860365 100644
--- a/Core/Multilayer/IInterferenceFunctionStrategy.h
+++ b/Core/Multilayer/IInterferenceFunctionStrategy.h
@@ -3,8 +3,7 @@
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
 //! @file      Core/Multilayer/IInterferenceFunctionStrategy.h
-//! @brief     Defines classes IInterferenceFunctionStrategy,
-//!              IInterferenceFunctionStrategy1, IInterferenceFunctionStrategy2
+//! @brief     Defines class IInterferenceFunctionStrategy.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -35,10 +34,9 @@ class SimulationElement;
 //! Base class of all interference function strategy classes.
 //! Provides an 'evaluate' function that computes the total scattering intensity
 //! from a decorated layer, taking into account a specific inter-particle interference function.
-//! This function uses low-level functions precomputeParticleFormfactors, evaluateForList
-//! that are implemented differently in different inheriting classes.
+//! This function uses the low-level function evaluateForList
+//! that is overriden in the derived classes.
 //! Inheritance is used to support scalar and polarized scattering
-//! (through IInterferenceFunctionStrategy1, IInterferenceFunctionStrategy2)
 //! and to implement different approximation schemes
 //! (DecouplingApproximationStrategy1, SSCApproximationStrategy1, and their polarized
 //! counterparts).
@@ -51,6 +49,9 @@ class SimulationElement;
 class BA_CORE_API_ IInterferenceFunctionStrategy
 {
 public:
+    typedef std::vector<Eigen::Matrix2cd, Eigen::aligned_allocator<Eigen::Matrix2cd>>
+        matrixFFVector_t;
+
     IInterferenceFunctionStrategy(const SimulationOptions& sim_params);
     virtual ~IInterferenceFunctionStrategy();
 
@@ -62,7 +63,10 @@ public:
 
 protected:
     virtual void strategy_specific_post_init() {}
-    virtual void precomputeParticleFormfactors(const SimulationElement& sim_element) const =0;
+    static std::vector<complex_t> precomputeScalar(const SimulationElement& sim_element,
+            const SafePointerVector<FormFactorCoherentSum>& ff_wrappers);
+    static matrixFFVector_t precomputePolarized(const SimulationElement& sim_element,
+            const SafePointerVector<FormFactorCoherentSum>& ff_wrappers);
 
     //! Evaluates the intensity for given list of evaluated form factors
     virtual double evaluateForList(const SimulationElement& sim_element) const =0;
@@ -80,33 +84,4 @@ private:
 #endif
 };
 
-//! Base class of all scalar interference function strategy classes.
-//! Provides the precomputation of particle form factors.
-
-class BA_CORE_API_ IInterferenceFunctionStrategy1 : public IInterferenceFunctionStrategy
-{
-public:
-    IInterferenceFunctionStrategy1(const SimulationOptions& sim_params);
-
-protected:
-    mutable std::vector<complex_t> m_precomputed_ff1; //!< cached form factor evaluations
-    void precomputeParticleFormfactors(const SimulationElement& sim_element) const final;
-};
-
-//! Base class of all polarized interference function strategy classes.
-//! Provides the precomputation of particle form factors.
-
-class BA_CORE_API_ IInterferenceFunctionStrategy2 : public IInterferenceFunctionStrategy
-{
-public:
-    IInterferenceFunctionStrategy2(const SimulationOptions& sim_params);
-
-    typedef std::vector<Eigen::Matrix2cd, Eigen::aligned_allocator<Eigen::Matrix2cd>>
-        matrixFFVector_t;
-
-protected:
-    mutable matrixFFVector_t m_precomputed_ff2; //!< cached polarized form factors
-    void precomputeParticleFormfactors(const SimulationElement& sim_element) const final;
-};
-
 #endif // IINTERFERENCEFUNCTIONSTRATEGY_H
diff --git a/Core/Multilayer/SSCApproximationStrategy.cpp b/Core/Multilayer/SSCApproximationStrategy.cpp
index f8844f3ec7d5c8cf3db07f4606f634ceec80c518..3c3413ce399699bd9e4e5dc11d0f55ac8f887f24 100644
--- a/Core/Multilayer/SSCApproximationStrategy.cpp
+++ b/Core/Multilayer/SSCApproximationStrategy.cpp
@@ -23,7 +23,7 @@
 // ************************************************************************** //
 
 SSCApproximationStrategy1::SSCApproximationStrategy1(SimulationOptions sim_params, double kappa)
-    : IInterferenceFunctionStrategy1(sim_params)
+    : IInterferenceFunctionStrategy(sim_params)
     , m_helper(kappa)
 {}
 
@@ -39,27 +39,29 @@ double SSCApproximationStrategy1::evaluateForList(const SimulationElement& sim_e
 {
     double qp = sim_element.getMeanQ().magxy();
     double diffuse_intensity = 0.0;
+    auto precomputed_ff = precomputeScalar(sim_element, m_formfactor_wrappers);
     for (size_t i = 0; i < m_formfactor_wrappers.size(); ++i) {
-        complex_t ff = m_precomputed_ff1[i];
+        complex_t ff = precomputed_ff[i];
         double fraction = m_formfactor_wrappers[i]->relativeAbundance();
         diffuse_intensity += fraction * std::norm(ff);
     }
-    complex_t mean_ff_norm  = getMeanFormfactorNorm(qp);
+    complex_t mean_ff_norm  = getMeanFormfactorNorm(qp, precomputed_ff);
     complex_t p2kappa = m_helper.getCharacteristicSizeCoupling(qp, m_formfactor_wrappers);
     complex_t omega = m_helper.getCharacteristicDistribution(qp, mP_iff.get());
     double interference_intensity = 2.0 * (mean_ff_norm * omega / (1.0 - p2kappa * omega)).real();
     return diffuse_intensity + interference_intensity;
 }
 
-complex_t SSCApproximationStrategy1::getMeanFormfactorNorm(double qp) const
+complex_t SSCApproximationStrategy1::getMeanFormfactorNorm(
+        double qp, const std::vector<complex_t>& precomputed_ff) const
 {
     complex_t ff_orig=0., ff_conj=0.; // original and conjugated mean formfactor
     for (size_t i = 0; i < m_formfactor_wrappers.size(); ++i) {
         double radial_extension = m_formfactor_wrappers[i]->radialExtension();
         complex_t prefac = m_formfactor_wrappers[i]->relativeAbundance()
             * m_helper.calculatePositionOffsetPhase(qp, radial_extension);
-        ff_orig += prefac * m_precomputed_ff1[i];
-        ff_conj += prefac * std::conj(m_precomputed_ff1[i]);
+        ff_orig += prefac * precomputed_ff[i];
+        ff_conj += prefac * std::conj(precomputed_ff[i]);
     }
     return ff_orig * ff_conj;
 }
@@ -69,7 +71,7 @@ complex_t SSCApproximationStrategy1::getMeanFormfactorNorm(double qp) const
 // ************************************************************************** //
 
 SSCApproximationStrategy2::SSCApproximationStrategy2(SimulationOptions sim_params, double kappa)
-    : IInterferenceFunctionStrategy2(sim_params)
+    : IInterferenceFunctionStrategy(sim_params)
     , m_helper(kappa)
 {}
 
@@ -87,13 +89,14 @@ double SSCApproximationStrategy2::evaluateForList(const SimulationElement& sim_e
 {
     double qp = sim_element.getMeanQ().magxy();
     Eigen::Matrix2cd diffuse_matrix = Eigen::Matrix2cd::Zero();
+    auto precomputed_ff = precomputePolarized(sim_element, m_formfactor_wrappers);
     for (size_t i = 0; i < m_formfactor_wrappers.size(); ++i) {
-        Eigen::Matrix2cd ff = m_precomputed_ff2[i];
+        Eigen::Matrix2cd ff = precomputed_ff[i];
         double fraction = m_formfactor_wrappers[i]->relativeAbundance();
         diffuse_matrix += fraction * (ff * sim_element.getPolarization() * ff.adjoint());
     }
     Eigen::Matrix2cd mff_orig, mff_conj; // original and conjugated mean formfactor
-    getMeanFormfactors(qp, mff_orig, mff_conj);
+    getMeanFormfactors(qp, mff_orig, mff_conj, precomputed_ff);
     complex_t p2kappa = m_helper.getCharacteristicSizeCoupling(qp, m_formfactor_wrappers);
     complex_t omega = m_helper.getCharacteristicDistribution(qp, mP_iff.get());
     Eigen::Matrix2cd interference_matrix
@@ -108,7 +111,8 @@ double SSCApproximationStrategy2::evaluateForList(const SimulationElement& sim_e
 
 //! Computes ff_orig and ff_conj.
 void SSCApproximationStrategy2::getMeanFormfactors(
-    double qp, Eigen::Matrix2cd& ff_orig, Eigen::Matrix2cd& ff_conj) const
+    double qp, Eigen::Matrix2cd& ff_orig, Eigen::Matrix2cd& ff_conj,
+    const matrixFFVector_t& precomputed_ff) const
 {
     ff_orig=Eigen::Matrix2cd::Zero();
     ff_conj=Eigen::Matrix2cd::Zero();
@@ -116,7 +120,7 @@ void SSCApproximationStrategy2::getMeanFormfactors(
         double radial_extension = m_formfactor_wrappers[i]->radialExtension();
         complex_t prefac = m_formfactor_wrappers[i]->relativeAbundance()
             * m_helper.calculatePositionOffsetPhase(qp, radial_extension);
-        ff_orig += prefac * m_precomputed_ff2[i];
-        ff_conj += prefac * m_precomputed_ff2[i].adjoint();
+        ff_orig += prefac * precomputed_ff[i];
+        ff_conj += prefac * precomputed_ff[i].adjoint();
     }
 }
diff --git a/Core/Multilayer/SSCApproximationStrategy.h b/Core/Multilayer/SSCApproximationStrategy.h
index 332edd3d7cb74182db9c6c4805cb723809fb517d..9b20ba41b552f1f26b855615678d50164ce2786d 100644
--- a/Core/Multilayer/SSCApproximationStrategy.h
+++ b/Core/Multilayer/SSCApproximationStrategy.h
@@ -25,7 +25,7 @@ class SimulationElement;
 //! in size-spacing correlation approximation.
 //! @ingroup algorithms_internal
 
-class SSCApproximationStrategy1 final : public IInterferenceFunctionStrategy1
+class SSCApproximationStrategy1 final : public IInterferenceFunctionStrategy
 {
 public:
     SSCApproximationStrategy1(SimulationOptions sim_params, double kappa);
@@ -35,7 +35,7 @@ protected:
     double evaluateForList(const SimulationElement& sim_element) const override;
 
 private:
-    complex_t getMeanFormfactorNorm(double qp) const;
+    complex_t getMeanFormfactorNorm(double qp, const std::vector<complex_t>& precomputed_ff) const;
     SSCAHelper m_helper;
 };
 
@@ -44,7 +44,7 @@ private:
 //! in size-spacing correlation approximation.
 //! @ingroup algorithms_internal
 
-class SSCApproximationStrategy2 final : public IInterferenceFunctionStrategy2
+class SSCApproximationStrategy2 final : public IInterferenceFunctionStrategy
 {
 public:
     SSCApproximationStrategy2(SimulationOptions sim_params, double kappa);
@@ -54,7 +54,8 @@ protected:
     double evaluateForList(const SimulationElement& sim_element) const override;
 
 private:
-    void getMeanFormfactors(double qp, Eigen::Matrix2cd& ff_orig, Eigen::Matrix2cd& ff_conj) const;
+    void getMeanFormfactors(double qp, Eigen::Matrix2cd& ff_orig, Eigen::Matrix2cd& ff_conj,
+                            const matrixFFVector_t& precomputed_ff) const;
     SSCAHelper m_helper;
 };