将 Kotlin 函数式编程代码转换为面向对象 类

Converting Kotlin functional programming code to object oriented classes

我在函数式编程中有设计模式 Chain Of Resposibility 的代码。我正在尝试将其转换为常规 OOP classes。以下是设计模式的工作代码:

函数式编程代码

enum class LogLevel {
    INFO, DEBUG, WARNING, ERROR, FUNCTIONAL_MESSAGE, FUNCTIONAL_ERROR;

    companion object {
        public fun all(): Array<LogLevel> {
            return values()
        }
    }
}

/**
 * Handler: Contains a method for building a chain of handlers. 
 * It also declares a method for executing a request.
 */
fun interface Logger {
    fun message(message: String, severity: LogLevel)

    fun appendNext(nextLogger: Logger): Logger {
        return Logger { message, severity ->
            message(message, severity)
            nextLogger.message(message, severity)
        }
    }
}

/**
 * Base Handler: Base handler is an optional class where you can put the boilerplate
 * code that’s common to all handler classes.
 *
 * @param writeMessage is the container that acts as the next link in the chain of handlers.
 */
fun writeLogger(vararg levels: LogLevel,
    writeMessage: (String) -> Unit
): Logger {
    val specifiedLevelsSet = EnumSet.copyOf(listOf(*levels))
    return Logger { message, requestedLogLevel ->
        if (specifiedLevelsSet.contains(requestedLogLevel)) {
            writeMessage(message)
        }
    }
}

/**
 * Concrete Handlers: Concrete handlers contain the actual code for processing requests.
 */
fun consoleLogger(vararg levels: LogLevel) =
    writeLogger(*levels) { message -> System.err.println("Writing to console: $message") }

fun emailLogger(vararg levels: LogLevel) =
    writeLogger(*levels) { message -> System.err.println("Sending via email: $message") }

fun fileLogger(vararg levels: LogLevel) =
    writeLogger(*levels) { message -> System.err.println("Writing to Log File: $message") }

/**
 * Client:
 */
fun main() {

    // Build an immutable chain of responsibility
    val logger = consoleLogger(*LogLevel.all())
        .appendNext(emailLogger(LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR))
        .appendNext(fileLogger(LogLevel.WARNING, LogLevel.ERROR))

    // Handled by consoleLogger since it has been set to log all levels
    logger.message("Entering function ProcessOrder().", LogLevel.DEBUG)
    logger.message("Order record retrieved.", LogLevel.INFO)

    // Handled by consoleLogger and emailLogger since the emailLogger
    // implements FUNCTIONAL_ERROR & FUNCTIONAL_MESSAGE
    logger.message(
        "Unable to Process Order ORD1 Dated D1 For Customer C1.",
        LogLevel.FUNCTIONAL_ERROR
    )
    logger.message("Order Dispatched.", LogLevel.FUNCTIONAL_MESSAGE)

    // Handled by consoleLogger and fileLogger since fileLogger implements WARNING & ERROR
    logger.message("Customer Address details missing in Branch DataBase.", LogLevel.WARNING)
    logger.message("Customer Address details missing in Organization DataBase.", LogLevel.ERROR)
}

出于学习目的,我将函数式编程代码转换为常规 classes。我将 fun interface 转换为常规 interface 并将函数 writeLogger() 转换为抽象 class/regular class BaseLoggerconsoleLogger() 到 class ConsoleLoggeremailLogger()EmailLogger等等。


问题

以下是我目前管理的 OOP 代码,但是 EmailLogger 没有被上面写的同一个 main() 函数调用:


OOP classes

abstract class Logger(vararg levels: LogLevel) {
    private var nextLogger: Logger? = null
    private val specifiedLevelsSet = EnumSet.copyOf(listOf(*levels))

    fun appendNext(nextLogger: Logger): Logger {
        this.nextLogger = nextLogger
        return this
    }

    fun message(message: String, severity: LogLevel) {
        if (specifiedLevelsSet.contains(severity)) {
            log(message)
        }

        nextLogger?.message(message, severity)
    }

    abstract fun log(message: String)
}

class ConsoleLogger(vararg level: LogLevel) : Logger(*level) {
    override fun log(message: String) {
        System.err.println("Writing to console: $message")
    }
}

class EmailLogger(vararg level: LogLevel) : Logger(*level) {
    override fun log(message: String) {
        System.err.println("Sending via email: $message")
    }
}

class FileLogger(vararg level: LogLevel) : Logger(*level) {
    override fun log(message: String) {
        System.err.println("Writing to Log File: $message")
    }
}

如有任何意见,我们将不胜感激。

基本处理程序

我将 fun interface 替换为 abstract class 并具有链条制作能力:

abstract class Logger(vararg levels: LogLevel) {
    private var nextLogger: Logger? = null
    private val specifiedLevelsSet = EnumSet.copyOf(listOf(*levels))

    fun appendNext(nextLogger: Logger) {
        this.nextLogger = nextLogger
    }

    fun message(message: String, severity: LogLevel) {
        if (specifiedLevelsSet.contains(severity)) {
            log(message)
        }

        nextLogger?.message(message, severity)
    }

    abstract fun log(message: String)
}

具体处理程序

将实现函数转换为各种类:

class ConsoleLogger(vararg level: LogLevel) : Logger(*level) {
    override fun log(message: String) {
        System.err.println("Writing to console: $message")
    }
}

class EmailLogger(vararg level: LogLevel) : Logger(*level) {
    override fun log(message: String) {
        System.err.println("Sending via email: $message")
    }
}

class FileLogger(vararg level: LogLevel) : Logger(*level) {
    override fun log(message: String) {
        System.err.println("Writing to Log File: $message")
    }
}

客户

fun main() {
    // Build an immutable chain of responsibility
    val logger = ConsoleLogger(*LogLevel.all())
    val emailLogger = EmailLogger(LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR)
    val fileLogger = FileLogger(LogLevel.WARNING, LogLevel.ERROR)

    logger.appendNext(emailLogger)
    emailLogger.appendNext(fileLogger)

    // Handled by consoleLogger since it has been set to log all levels
    logger.message("Entering function ProcessOrder().", LogLevel.DEBUG)
    logger.message("Order record retrieved.", LogLevel.INFO)

    // Handled by consoleLogger and emailLogger since the emailLogger
    // implements FUNCTIONAL_ERROR & FUNCTIONAL_MESSAGE
    logger.message(
        "Unable to Process Order ORD1 Dated D1 For Customer C1.",
        LogLevel.FUNCTIONAL_ERROR
    )
    logger.message("Order Dispatched.", LogLevel.FUNCTIONAL_MESSAGE)

    // Handled by consoleLogger and fileLogger since fileLogger implements WARNING & ERROR
    logger.message("Customer Address details missing in Branch DataBase.", LogLevel.WARNING)
    logger.message("Customer Address details missing in Organization DataBase.", LogLevel.ERROR)
}