所以我有以下项目要完成。我还没决定如何设计它。会喜欢一些建议。
它基本上是一个表归档器。 Givend需要在另一个地方导出这些行的特定条件。 这个地方可能是另一个数据库或(s)ftp服务器。 如果您选择数据库,则每次达到某个限制时都需要创建一个表(例如每个表不超过50k行),如果您选择一个(s)ftp服务器,那么您需要编写一个CSV或XML并将其放入在那里存档。
所以我们有这些组合:
现在,我看到了所有地方的AbstractFactory模式,但基于什么? 我的想法是我应该有SQLWriter,XMLWriter,CSVWriter,它继承了一个抽象的Writer类,它实现了一些常见的策略,如计算行,获取常见的配置参数等...... 我应该为Connection类/接口做同样的事情(因为sql和(s)ftp真的不同吗?
如果您需要更多信息,请询问。
答案 0 :(得分:2)
听起来你正走在正确的道路上。
您应该避免创建作为Writer和Connection组合的类,而是创建某种包含Writer接口和Connection接口(作为属性)的Manager类。然后创建每个的适当实现并将它们传递给Manager。
这是战略设计模式的经典用法。
修改:添加代码示例。您应该添加适当的错误检查。
class Writer
{
public:
virtual void output(cons std::string &data) = 0;
};
class Format
{
public:
virtual std::string serialize() = 0;
};
// Create concrete Writer and Format classes here
class OutputManager
{
public:
// Notice there should be no Writer, Format creation logic here,
// This class should focus on orchestrating the output
OutputManager() : writer_(NULL), format_(NULL) {}
OutputManager(Writer *w, Format *f) : writer_(w), format_(f) {}
void setWriter(Writer *w) { writer_ = w; }
Writer *getWriter() { return writer_; }
void setFormat(Format *f) { format_ = f; }
Format *getFormat() { return format_; }
// Maybe this should have a different return type
void doOutput()
{
// Not sure what else you would need here,
// but this is an example usage
writer_->output(format_->serialize());
}
private:
Writer *writer_;
Format *format_;
};
//
// And now the factories
//
class OutputAbstractFactory
{
public:
OutputAbstractFactory(Config *c) config_(c) {}
void createFactories()
{
writerFactory_ = WriterAbstractFactory::getWriterFactory(config_);
formatFactory_ = FormatAbstractFactory::getFormatFactory(config_);
}
Writer *getWriter() { return writerFactory_->getWriter(); }
Format *getFormat() { return formatFactory_->getFormat(); }
private:
WriterAbstractFactory *writerFactory_;
FormatAbstractFactory *formatFactory_;
Config *config_;
}
class WriterAbstractFactory
{
public:
// Config is a class you will have to make with
// the info detailing the Writer and Format stuff
static WriterAbstractFactory *getWriterFactory(Config *c);
virtual Writer *getWriter() = 0;
};
class FormatAbstractFactory
{
public:
// Config is a class you will have to make with
// the info detailing the Writer and Format stuff
static FormatAbstractFactory *getFormatFactory(Config *c);
virtual Format *getFormat() = 0;
};
// Create concrete factories here
//
// And this ties it all together
//
int main(int argc, char **argv)
{
Config c;
// populate Config accordingly
OutputAbstractFactory *factory(&c);
factory.createFactories();
Writer *w = factory->getWriter();
Format *f = factory->getFormat();
// Do whatever else you need to with the Writer/Format here
OutputManager om(w, f);
// Do whatever else you need with the OutputManager here
om.doOutput();
}
答案 1 :(得分:0)
您可能希望获得Modern C++ Design的副本,以获取有关如何制作基于策略的通用转换工具的建议。下面是一个非常粗略的骨架,它在两个策略上进行参数化:格式和连接。
template
<
typename FormatPolicy, // SQL, XML, CSV, provides row, config functionality
typename ConnectionPolicy // SQL, FTP, provides open/close/read/write functionality
>
class ConversionTool
:
public FormatPolicy,
public ConnectionPolicy
{
public:
// your conversion interface here
void operator()( /* your input */, /* your output */);
};
class SQLFormat { // SQL specific stuff } ;
class SQLConnection { // SQL specific stuff };
typedef ConversionTool<SQLFormat, SQLConnection> SQL2OurCustomerSQL;
SQL2OurCustomerSQL()(in_file, out_file); // for elsewhere declared in_file / out_file
答案 2 :(得分:0)
您正在处理两个问题。一种是格式,另一种是持久化的目的地。对于格式,您需要序列化器,对于目的地,您需要适配器。 SqlSerializer,XMLserializer。 SQLDestination,FTPDestination atc。
伪代码看起来像:
new Destination(new Serializer(SourceData))。persist();
interface DataSerializer{
String serialize();
}
class SqlSerializer implements DataSerializer {
final Object rawData;
SqlSerializer(Object rawData) {
this.rawData = rawData;
}
String serialize() {
// SQL Serialization Logic
}
}
class XmlSerializer implements DataSerializer {
final Object rawData;
XmlSerializer(Object rawData) {
this.rawData = rawData;
}
String serialize() {
// XML Serialization Logic
}
}
interface Destination {
void persist(DataSerializer dataSerializer);
}
class SqlDestination implements Destination {
final String username;
...
...
SqlDestination(String username, String password, String url) {
this.username = username;
...
...
}
void persist(DataSerializer dataSerializer) {
// open SQL connection
String = dataSerialize.serialize();
// do sqlPersistanceLogic
}
}
class FtpDestination implements Destination {
final String username;
...
...
FtpDestination(String username, String password, String url) {
this.username = username;
...
...
}
void persist(DataSerializer dataSerializer) {
// open FTP session connection
String = dataSerialize.serialize();
// send to ftpDestination
}
}
Call:
Destination dest = getApropriateDestination();
dest.persist(new XmlSerializer(rawData));
您还可以实现逻辑以验证特定Destination的受支持序列化程序,或者如果目标和序列化程序之间存在1:1关系,则可以使用模板化。但我不知道它在C ++中是怎么回事;
根据您使用的工具和框架,您可以实施三种提取方式之一。原则仍然存在