Qtの基礎 - シングルトン

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

オブジェクト指向のプログラム言語のクラスのデザインパターンの1種である。
デザインパターンとは、オブジェクト指向の言語で使用される設計のパターンのことであり、設計時に直面する問題とその解決策を整理してまとめたものを指す。

シングルトンは、クラスの設計方法の1つであり、クラスのインスタンスを2つ以上生成できないようにすることで、常に同一のインスタンスが参照されるデザインパターンとなる。
例えば、インスタンスの状態を常に持つ場合やクラス端で共通のデータとしてアクセスする必要がある場合に使用される。


使用例 : ログクラス

ログファイルの操作を行うクラスをシングルトンパターンで設計することは、
アプリケーション全体で1つのログファイルインスタンスのみを保持して、統一されたアクセスポイントを提供するための一般的な方法である。

シングルトンパターンを使用することにより、異なるコンポーネントからのログメッセージが1つのログファイルに順序よく書き込まれることが保証できる。

以下の例では、指定されたパスでログファイルを開き、ログファイルになんらかの文字列を書き込んでいる。
もし、ログファイルが存在しない場合はファイルを作成する。
また、ファイルのオープンに失敗した場合はエラーを返す。

 // Logger.hファイル
 
 #ifndef LOGGER_H
 #define LOGGER_H
 
 #include <QCoreApplication>
 #include <QFile>
 #include <QTextStream>
 
 class Logger {
 private:
    bool        m_LogFileOpened;
    QFile       m_LogFile;
    QTextStream m_Textout;
 
 private:
    Logger();  // プライベートコンストラクタ
    ~Logger(); // デストラクタ
    Logger(const Logger &rhs) = delete; // コピー禁止
    Logger &operator=(const Logger &rhs) = delete; // 代入禁止
    bool isLogFileOpen() const;
 
 public:
    static Logger& instance();
    void writeLog(const QString &message);
 };
 
 #endif // LOGGER_H


 // Logger.cpp
 
 #include <QFileInfo>
 #include "logger.h"

 Logger::Logger() : m_LogFileOpened(false)
 {
 }
 
 Logger::~Logger()
 {
    if (m_LogFile.isOpen()) {
       m_LogFile.close();
    }
 }
 
 Logger& Logger::instance(const QString &filePath)
 {
    static Logger instance;  // シングルトンインスタンスの生成
 
    if (!instance.m_LogFile.isOpen() && !filePath.isEmpty()) {
       // ログファイルを開く
       instance.m_LogFile.setFileName(filePath);
       instance.m_LogFileOpened = instance.m_LogFile.open(QIODevice::WriteOnly | QIODevice::Append);
       if (instance.m_LogFileOpened) {
          instance.m_Textout.setDevice(&instance.m_LogFile);
       }
    }
 
    return instance;
 }
 
 void Logger::writeLog(const QString &message)
 {
    if (m_LogFileOpened) {
       // ファイルを直ちに書き込む
       m_Textout << message << "\n";
       m_Textout.flush();
    }
 }
 
 bool Logger::isLogFileOpen() const
 {
    return m_LogFileOpened;
 }


上記のクラスでは、Loggerクラスのインスタンスを取得する時に、ログファイルのパスをinstanceメソッドに渡す。
Loggerクラスのインスタンスが初めて要求された時、指定されたパスでログファイルを開こうと試みる。

ログファイルが存在しない場合は、ファイルを新規作成する。
ログファイルの作成に失敗した場合は、writeLogメソッドを呼び出しても何も処理が行われないようにエラーハンドリングしている。

また、isLogFileOpenメソッドを実行することにより、ログファイルが正常に開かれたかどうかを確認することができる。

 QString logFilePath = "/tmp/logfile.log";
 
 Logger &logger = Logger::instance(logFilePath);
 if (logger.isLogFileOpen()) {
    logger.writeLog("This is a sample message.");
 }
 else {
    // ログファイルのオープンに失敗した場合
    // ...略
 }