首页 > 解决方案 > 将 Kotlin 函数式编程代码转换为面向对象的类

问题描述

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

函数式编程代码

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)
}

出于学习目的,我将函数式编程代码转换为常规类。我转换fun interface为常规interface和函数到writeLogger()抽象类/常规类BaseLoggerconsoleLogger()到类ConsoleLogger,等等。emailLogger()EmailLogger


问题

以下是我迄今为止管理的 OOP 代码,但EmailLogger没有被上面编写的相同 main() 函数调用:


面向对象课程

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")
    }
}

任何输入将不胜感激。

标签: kotlindesign-patternsfunctional-programmingchain-of-responsibility

解决方案


基础处理程序

我用链制造能力替换fun interfaceabstract 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)
}

推荐阅读