我正在编写一个简单的原型代码来演示&用于物理代码的配置文件I / O方案(HDF4,HDF5,HDF5,使用并行IO,NetCDF等)。由于重点是IO,程序的其余部分非常简单:
class Grid
{
public:
floatArray x,y,z;
};
class MyModel
{
public:
MyModel(const int &nip1, const int &njp1, const int &nkp1, const int &numProcs);
Grid grid;
map<string, floatArray> plasmaVariables;
};
其中floatArray
是一个简单的类,它允许我定义任意尺寸的数组并对它们进行数学运算(即x + y是逐点加法)。
当然,我可以使用更好的封装(写访问器/设置器等),但这不是我正在努力的概念。对于I / O例程,我正在设想应用简单继承:
代码应该以任何这些格式读取数据,然后写出任何这些格式。在过去,我会向myModel添加一个AbstractIO
成员,并根据我想要的I / O方案创建/销毁此对象。通过这种方式,我可以做类似的事情:
myModelObj.ioObj->read('input.hdf')
myModelObj.ioObj->write('output.hdf')
我有一些OOP经验但在设计模式方面很少,所以我最近获得了Gang of Four book "Design Patterns: Elements of Reusable Object-Oriented Software"。 OOP设计人员:您建议我使用哪种模式将I / O与myModel
对象集成?我有兴趣回答这个问题有两个原因:
我倾向于将欺骗者模式应用于myModel
,因此我可以动态地将I / O职责附加到myModel
(即是否使用HDF4,HDF5等)。但是,我不觉得这是适用的最佳模式。在开始编码之前阅读“四人帮”一书的封面感觉就像是一种培养不健康的咖啡因成瘾的好方法。你推荐什么样的模式?
答案 0 :(得分:10)
只需编写代码即可。当你编写它时,尝试在你编写的代码中识别模式(更重要的是不仅仅是GOF模式)。如果你不能,不要担心 - 在你的下一个项目中,只需再次编写代码,然后再次尝试识别该模式和第一个项目中的模式。这就是所有的设计模式 - 你反复做的事情。一旦你至少有一点点经验,他们只会明智地谈论。 GOF书籍不是一个解决方案目录。
答案 1 :(得分:4)
“您建议我使用哪种模式将I / O与myModel对象集成?”
你问的是错误的问题。您应该问的问题是,“我如何将我的模型与I / O分开?”
有很多答案。我见过的一个有趣的设置是Robert C. Martin使用代理。您使用装饰器的想法也有其优点。
我强烈反对那些告诉你不要担心模式的人。确实,您应该让问题决定解决方案,但在您真正尝试使用模式之前,您永远不会学会识别它们,也不能在架构讨论中使用它们;模式对于能够讨论设计和架构非常重要,如果你没有词汇,那么在这样的讨论中你就会受到严重的妨碍。
或许比模式更重要的是学习导致它们的原则。学习开放/封闭原则(主要原则)和LSP。还要记住单一责任原则等原则。设计模式源于遵循这些原则,因此非常了解它们将有助于您识别何时可以应用模式以及为什么某个特定模式可以比其他模式更有帮助。
答案 2 :(得分:3)
我同意Neil的意见,因为最好“发现”代码中处于休眠状态的模式,而不是试图将现成的想法强加给您的设计。为此,我推荐Josh Kerievsky撰写的Refactoring to Patterns - 这是一本值得阅读的内容,可让您深入了解如何在日常开发工作中实际使用和处理模式。
那说,装饰器是用的,例如在Java IO Stream库中,所以你的想法有先例: - )
答案 3 :(得分:1)
就个人而言,我不打算试图找出适用的模式。相反,我会简单地关注如何修改代码以使其更具可读性和可维护性。
在某些时候,你会做到这一点,真正的模式将开始出现。在那时,请回到GoF书籍,找出如何最好地调整它们。
答案 4 :(得分:1)
嗯,这是一个包含C ++设计模式示例的网站(开头):Vince Huston。设计极简主义,但它提供了示例和建议。
对于您的问题,我认为Decorator
不合适。 Decorator
的目标是添加一些内容。传统的例子是在油漆上添加一个框架。
我认为你在考虑Strategy
。 Strategy
的想法是在运行时选择如何执行任务。它通常与AbstractFactory
结合使用,给出一个关键返回正确的具体策略。
例如,假设您根据文件的扩展名选择策略:
class IDecoder
{
public:
virtual void execute(Model& model, File const& file) const = 0;
private:
};
class HDF4: public IDecoder
{
public:
virtual void execute(Model& model, File const& file) const;
private:
};
class DecoderFactory
{
public:
static std::auto_ptr<IDecoder> Get(std::string const& fileName);
private:
};
class Model
{
public:
Model(std::string const& fileName)
{
std::auto_ptr<IDecoder> decoder = DecoderFactory::Get(fileName);
File file(fileName);
decoder->execute(*this, file);
}
};