2

だから私は達成するために次のプロジェクトを持っています。とはいえ、どのようにデザインするかはまだ決まっていません。アドバイスをいただければ幸いです。

これは基本的にテーブル アーカイバです。特定の条件を考えると、それらの行を別の場所にエクスポートする必要があります。この場所は、別のデータベースまたは (s)ftp サーバーである可能性があります。データベースを選択した場合、特定の制限 (テーブルあたり 5 万行以下など) に達するたびにテーブルを作成する必要があります。(s)ftp サーバーを選択した場合は、CSV または XML を記述して、そこにファイル。

したがって、これらの組み合わせがあります。

  1. sql2CustomerSql
  2. sql2Oursql (このために、システム構成に基づいて接続して情報を取得するためのクラスを既に作成しています)
  3. csv2ftp
  4. csv2sftp
  5. xml2ftp
  6. xml2sftp

さて、至る所に AbstractFactory パターンが見られますが、何に基づいているのでしょうか? 私の考えでは、行のカウント、共通の構成パラメーターの取得などの共通のポリシーを実装する抽象的な Writer クラスからすべてを継承する SQLWriter、XMLWriter、CSVWriter が必要であるということです... Connection クラス/インターフェイスに対して同じことを行う必要があります (なぜならsql と (s)ftp は本当に違うのですか?

さらに情報が必要な場合は、お尋ねください。

4

3 に答える 3

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();
}
于 2012-04-27T11:10:13.113 に答える
0

ポリシーベースの汎用変換ツールを作成する方法についてのアイデアを得るために、 Modern C++ Designのコピーを入手することをお勧めします。以下は、フォーマットと接続の 2 つのポリシーでパラメーター化された非常に大雑把なスケルトンです。

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
于 2012-04-27T12:37:54.657 に答える
0

あなたは2つの問題に取り組んでいます。1 つはフォーマットで、もう 1 つは保存先です。フォーマットにはシリアライザーが必要で、宛先にはアダプターが必要です。SqlSerializer、XMLserializer。SQLDestination、FTPDestination atc.

疑似コードは次のようになります。

  • Destination.persist(new Serializer(SourceData));
  • Destination.persist(Serializer.transform(SourceData));
  • 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));
    

特定の送信先に対してサポートされているシリアライザーを検証するロジックを実装することもできます。または、送信先とシリアライザーの間に 1:1 の関係がある場合は、テンプレートを使用できます。しかし、それが C++ でどのようになっているのかはわかりません。

使用するツールとフレームワークに基づいて、推奨される 3 つの方法のいずれかを実装できます。原則のまま

于 2012-04-27T13:14:32.380 に答える