C + + design pattern - decoration pattern

Decoration mode

Decoration mode refers to dynamically extending the function of an object without changing the original class file and using inheritance. It wraps the real object by creating a wrapper object, that is, decoration-- Baidu Encyclopedia

Decorator mode is mainly to add new behavior to an object. The effect is similar to that of subclass extending parent class, but the implementation method is different from inheritance, and it is more flexible.

Decoration pattern class diagram

Componet: defines the interface base class.

ConcreteComponent: the concrete decorated target object.

Decorator: decoration class base class.

ConcreteDecoratorA: specific decoration class A

ConcreteDecoratorB: specific decoration class B

Application scenario

actual demand

Realize a customized log, including log printing, adding time stamp, printing to terminals and files, etc.

analysis

One of the most basic log functions is to print and output the code debugging to the specified file. Now it is necessary to add time stamp and terminal display functions on this basis. According to the previous writing method, directly modifying the log function code may cause the following problems:

  • The log function is referenced too much, and a slight carelessness will cause compilation problems.
  • The log function tends to be stable. Direct modification may add hidden bugs.

Solution

The decoration mode is introduced to encapsulate a layer of decoration code on the original log interface. In this way, there is no need to modify the original log code and ensure the development of new requirements.

Log class diagram

effect

Client code

int main(int argc, char *argv[])
{
    LOGI("main", "Welcome kaiyuan519!\n");
    LOGD("main", "Welcome kaiyuan519!\n");
    return 0;
}

Terminal printing

It can be seen from the above figure that not only the string printed by the client is output to the same level directory, but also the time stamp and terminal display functions are added.

Source code

The code is too long. This article only pastes the main code functions. You can enter all the source code in the background of the official account.

Client code

int main(int argc, char *argv[])
{
    LOGI("main", "Welcome kaiyuan519!\n");
    LOGD("main", "Welcome kaiyuan519!\n");
    return 0;
}

Reference modification class adds new features to log

// Custom log: add timestamp and terminal printing
int sys_log(int level, const char *tag, const char *msg)
{
    // Save to file
    if (!pLog) {
        pLog = CLog::GetInstance();
    }

    // Display at terminal
    if (!pLog2Terminal) {
        pLog2Terminal = CLog2Terminal::GetInstance(pLog);
    }

    // Add log debugging information: timestamp, level and label
    if (!pLogAddInfo) {
        pLogAddInfo = CLogAddInfo::GetInstance(pLog2Terminal);
    }

    // Interface for finishing decoration
    pLogAddInfo->SetLogLevel(level);
    pLogAddInfo->WriteLog(tag, msg);

    return 0;
}

Log add information code

int CLogAddInfo::WriteLog(const char *tag, const char *msg)
{
    char logStr[LOG_STR_LENGTH] = {0};  // The length of one log print shall not exceed 2000
    int length = 0;

    // log add debugging information: time, level, tag: 2022-01-14 10:09:51.106 I / < main >
    length = get_local_time(logStr);
    snprintf(logStr + length, LOG_STR_LENGTH - length, "%s <%s> %s", LEVEL_STR[levelIndex], tag, msg);

    CCustomLog::WriteLog(tag, logStr);
    return strlen(logStr);
}

Output to terminal code

int CLog2Terminal::WriteLog(const char *tag, const char *msg)
{
    // Output to terminal
    fprintf(stdout, "%s", msg);		// Add new function
    return CCustomLog::WriteLog(tag, msg);
}

summary

  • The implementation method of decoration mode is nothing more than encapsulating the original single function through layers of functional interfaces, and providing the encapsulated interface to the client. Since the functional interface is the same as the native interface, the use code of the client does not need to be changed.
  • The decoration mode is only part of changing its appearance, and the original function is retained.
  • When in use, the required functions can be added at will without modifying the original functions. It is also flexible to use.
  • The disadvantage is that the decoration mode has strict initialization requirements, and the code is difficult to understand. When the demand increases, many classes will be added. Therefore, new functions should be treated with caution.

Added by wombatee on Sun, 16 Jan 2022 16:13:53 +0200