我一直在阅读在线文章,并在阅读“Head First Design Patterns”的过程中,似乎其中一个基本的OOP是“封装变化的东西”。我被困在如何将其应用到我的问题上,甚至可能没有以正确的方式查看问题所以我希望得到一些建议。
我将总结我的应用程序,期望的目标和我面临的问题,而不是最后展示我的代码。我省略了代码的某些部分并简化了输入。我想,因为这更像是一个设计问题,我不需要显示所有的构造函数等等。
我的应用程序需要进行大量测量并通过我称之为估算器的方法处理测量:最小二乘(LS),扩展卡尔曼滤波器(EKF)或顺序最小二乘(SLS)。我想在运行时更改使用哪个估算器。
每个估算器基本上都有两个方法“Update()”和“DetectBlunders()”(并按此顺序调用),每个方法的内部结构根据估算器的不同而不同,但目标是相同的。所以我最初有一个“BaseEstimator”,它有方法“Update()”和“DetectBlunders()”,每个估算器都继承自“BaseEstimator”。通过实施具体的估算器,我开始意识到一些问题。
1)EXF在“Update()”之前需要一个额外的步骤“Predict()”。所以我最初为“BaseEstimator”添加了一个“Predict()”方法,在LS和SLS中,“Predict()”什么也没做。然而这种方式似乎有些错误。如果我更改了“Predict()”或将其从我的LS中的“BaseEstimator”中删除,那么SLS会受到影响,即使它们首先不应该有“Predict()”。
2)EKF和SLS需要一个额外的输入“Update()”。所以我做了类似的事情,我在“BaseEstimator”的“Update()”中添加了这个额外的输入,在LS的覆盖中,我只传递一个空变量。再次,这似乎是错误的。这个输入是另一个对象,所以我实际上只在LS中传递一个空构造函数,在LS中我测试构造函数是否为空,看起来非常错误。
如果有的话,有人会对我能做什么有任何建议。也许这是解决问题的唯一方法。最终目标是制作一个“EstimatorFactory”(我理解的唯一可以使用的设计原则),在运行时可以制作一个Estimator。我也可以在将来添加其他估算器,如“粒子滤波器(PF)”。再一次,我对实际使用OOP非常陌生,旧的我只会使用if / switch到处并且有一个类可以执行所有三个估算器(后来几千行)。
class BaseEstimator {
public:
// I dont actually call my inputs 1,2,3,4
virtual bool Update(
double input1, // Required by all three estimators
double input2, // Required by all three estimators
double input3, // Required by all three estimators
double input4 // Not required in LS, but required in EXF and SLS
);
virtual bool DetectBlunders() const = 0;
// Only required by EXF
virtual bool Predict(
double input1,
double input2
) = 0;
};
class EXF : public BaseEstimator {
public:
bool Update(
double input1,
double input2,
double input3,
double input4);
bool DetectBlunders() const;
bool Predict(
double input1,
double input2);
};
class LS : public BaseEstimator {
public:
bool Update(
double input1,
double input2,
double input3,
double input4 = 0 // This is not needed in LS so I actually pass it an empty constructor
);
bool DetectBlunders() const;
bool Predict(
double input1,
double input2) {
// Do nothing since its not required in LS
}
};
class SLS : public BaseEstimator {
public:
bool Update(
double input1,
double input2,
double input3,
double input4);
bool DetectBlunders() const;
bool Predict(
double input1,
double input2) {
// Do nothing since its not required in SLS
}
};
答案 0 :(得分:0)
我已经和OOP合作了一段时间,你所描述的并不罕见。
基类有2个角色。 1.隐藏其子女的具体实施。 2.保证给孩子们一定的信息。
构建估算器后,您应该专门使用BaseEstimator
。这将完全隐藏您正在使用的Estimator。允许您编写独立于Estimator特定实现的通用代码。
正因为如此,您将无法知道您使用的是哪个Estimator,而且您必须提供Estimator可能需要的所有信息。
所有儿童都可以访问相同的信息。唯一的区别是他们如何处理这些信息。
出于所有这些原因,您还希望为您的孩子班级提供一定程度的灵活性。在OOP框架中看到PreLoad
Loading
Loaded
方法并不罕见。这些方法为派生类提供了一定的灵活性和可扩展性。即使不是所有的孩子都使用Predict
方法,也可以提供这种可能性。