代码整洁之道 设计模式全解 2

本文详细介绍了四种常见的IT设计模式:责任链模式,用于解耦请求处理;装饰器模式,用于对象功能扩展;工厂方法模式,实现对象实例化延迟;以及回退策略,处理异常情况。通过实例代码展示了这些模式的应用和优势。
摘要由CSDN通过智能技术生成

目录

前言

正文

责任链模式优点

责任链模式示例代码

装饰器模式示例代码

工厂方法组成

工厂模式示例代码

回退策略示例代码

结尾


前言

责任链模式是一种行为设计模式,它允许将请求的发送者和接收者解耦,让多个对象都有机会处理这个请求。在这个模式中,这些对象形成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

装饰器模式是一种结构型设计模式,允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式作为现有类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持原类方法签名完整性的前提下,提供了额外的功能。

工厂方法,提供了一种创建对象的接口,让子类决定实例化哪一个类。工厂方法模式使一个类的实例化延迟到其子类。简而言之,工厂方法让类把实例化推迟到子类进行。在工厂方法模式中,不直接通过 new 关键字来创建对象,而是通过一个特定的方法(即工厂方法)来创建对象。这个方法通常由一个接口定义,并由子类实现,这样就可以在不直接依赖具体类的情况下生成对象,增加了代码的灵活性和可扩展性。

回退策略是一种错误处理或容错的设计模式,用于应对操作失败或异常情况。当一个操作失败时,系统将尝试一个或多个备用方案,以确保系统的稳定运行或至少能够优雅地处理错误。

正文

责任链模式优点

  • 降低耦合度。它将请求的发送者和接收者解耦。
  • 增强了给对象指派职责的灵活性。通过改变链内的成员或调整它们的次序,允许动态地新增或删除责任。
  • 增加了新的请求处理类很方便。

责任链模式示例代码

有一个日志记录的系统,根据日志的等级将信息输出到不同的地方:控制台、文件、网络等。‘

首先,定义日志等级和处理者抽象类:

enum class LogLevel {
    INFO, DEBUG, ERROR
}


abstract class Logger(protected var level: LogLevel) {
    private var nextLogger: Logger? = null

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

    fun logMessage(level: LogLevel, message: String) {
        if (this.level <= level) {
            write(message)
        }
        nextLogger?.logMessage(level, message)
    }

    abstract protected fun write(message: String)
}

配置责任链并使用:

fun main() {
    val consoleLogger = ConsoleLogger(LogLevel.INFO)
    val fileLogger = FileLogger(LogLevel.DEBUG).setNextLogger(consoleLogger)
    val networkLogger = NetworkLogger(LogLevel.ERROR).setNextLogger(fileLogger)

    networkLogger.logMessage(LogLevel.INFO, "This is an informational message.")
    networkLogger.logMessage(LogLevel.DEBUG, "This is a debug message.")
    networkLogger.logMessage(LogLevel.ERROR, "This is an error message.")
}

省略了ConsoleLogger等...logger的实现代码。 

装饰器模式示例代码

有一个简单的咖啡制作过程,我们希望能够动态地为咖啡添加各种调料,如牛奶、糖等。

首先,定义一个咖啡接口:

interface Coffee {
    fun cost(): Double
    fun ingredients(): String
}

实现基础咖啡类:

class BasicCoffee : Coffee {
    override fun cost() = 1.0
    override fun ingredients() = "Coffee"
}

创建装饰器基类:

abstract class CoffeeDecorator(protected val coffee: Coffee) : Coffee {
    override fun cost(): Double = coffee.cost()
    override fun ingredients(): String = coffee.ingredients()
}

实现具体的装饰器类:

class WithMilk(coffee: Coffee) : CoffeeDecorator(coffee) {
    override fun cost(): Double = super.cost() + 0.5
    override fun ingredients(): String = super.ingredients() + ", Milk"
}

class WithSugar(coffee: Coffee) : CoffeeDecorator(coffee) {
    override fun cost(): Double = super.cost() + 0.2
    override fun ingredients(): String = super.ingredients() + ", Sugar"
}

工厂方法组成

  • 产品接口:定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品:实现了产品接口的类,定义了要生成的具体产品的对象。
  • 创建者(Creator)类:声明了工厂方法,该方法返回一个产品类型的对象。创建者类的子类通常提供这个方法的实现。
  • 具体创建者:重写工厂方法以返回一个具体产品实例。

工厂模式示例代码

定义一个日志记录系统,可以根据不同的情况记录到不同的地方(例如,控制台、文件)。使用工厂方法模式来实现这一点。

首先,定义日志记录器接口和几种具体的日志记录器:

interface Logger {
    fun log(message: String)
}

class ConsoleLogger : Logger {
    override fun log(message: String) {
        println("Log to console: $message")
    }
}

class FileLogger : Logger {
    override fun log(message: String) {
        println("Log to file: $message")
    }
}

接下来,定义一个创建者抽象类和具体的创建者类:

abstract class LoggerFactory {
    abstract fun createLogger(): Logger

    fun getLogger(): Logger {
        
        return createLogger()
    }
}

class ConsoleLoggerFactory : LoggerFactory() {
    override fun createLogger(): Logger = ConsoleLogger()
}

class FileLoggerFactory : LoggerFactory() {
    override fun createLogger(): Logger = FileLogger()
}

 使用如下:

fun main() {
    val consoleLoggerFactory = ConsoleLoggerFactory()
    val consoleLogger = consoleLoggerFactory.getLogger()
    consoleLogger.log("This is a console log.")

    val fileLoggerFactory = FileLoggerFactory()
    val fileLogger = fileLoggerFactory.getLogger()
    fileLogger.log("This is a file log.")
}

回退策略示例代码

fun fetchData(): String {
    if (Random.nextInt(10) < 7) { 
        throw Exception("Network Error")
    }
    return "Data from server"
}

fun fetchDataWithFallbackStrategy(attempts: Int = 3): String {
    var lastException: Exception? = null

    for (i in 1..attempts) {
        try {
            return fetchData() 
        } catch (e: Exception) {
            lastException = e
            println("Attempt $i failed: ${e.message}")
        }
    }

    return "Fallback data" 
}

如上就是应用了回退策略的代码,有百分之70的概率NetWorkError,在attempts次数里多次尝试,如果均NetWorkError还能返回一个回退数据。

结尾

设计模式的英文是什么?Design pattern,这是一个非常之准确的词汇,个人认为比中文翻译好太多了。

Patten中文释义:. n. 模式;图案;样品. vt. 模仿

pattern往往意味着是一种既定的准则,从它的动词可以看到,他有模仿的意思,也就是说,这样的代码设计,是一系列前人留下的经验,只要跟着这样写代码,往往能够让你的代码,更加简洁,更加健壮,更加优雅!

我觉得他应该有个意译的名字,叫做:代码设计的最佳实践!

【设计模式自习室】开篇:为什么要有设计模式? - 知乎 (zhihu.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏目艾拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值